Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dff25ddb authored by Andreas Gruenbacher's avatar Andreas Gruenbacher Committed by Trond Myklebust
Browse files

nfs: add support for the umask attribute

Clients can set the umask attribute when creating files to cause the
server to apply it always except when inheriting permissions from the
parent directory.  That way, the new files will end up with the same
permissions as files created locally.

See https://tools.ietf.org/html/draft-ietf-nfsv4-umask-02

 for more details.

Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
parent d9152114
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -1529,8 +1529,13 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
		return -ENAMETOOLONG;

	if (open_flags & O_CREAT) {
		struct nfs_server *server = NFS_SERVER(dir);

		if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
			mode &= ~current_umask();

		attr.ia_valid |= ATTR_MODE;
		attr.ia_mode = mode & ~current_umask();
		attr.ia_mode = mode;
	}
	if (open_flags & O_TRUNC) {
		attr.ia_valid |= ATTR_SIZE;
+12 −4
Original line number Diff line number Diff line
@@ -1224,6 +1224,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
	atomic_inc(&sp->so_count);
	p->o_arg.open_flags = flags;
	p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
	p->o_arg.umask = current_umask();
	p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
	p->o_arg.share_access = nfs4_map_atomic_open_share(server,
			fmode, flags);
@@ -3337,7 +3338,7 @@ static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)

#define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL)
#define FATTR4_WORD2_NFS41_MASK (2*FATTR4_WORD2_SUPPATTR_EXCLCREAT - 1UL)
#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_SECURITY_LABEL - 1UL)
#define FATTR4_WORD2_NFS42_MASK (2*FATTR4_WORD2_MODE_UMASK - 1UL)

static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle)
{
@@ -4010,6 +4011,7 @@ static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
		 int flags)
{
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs4_label l, *ilabel = NULL;
	struct nfs_open_context *ctx;
	struct nfs4_state *state;
@@ -4021,6 +4023,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,

	ilabel = nfs4_label_init_security(dir, dentry, sattr, &l);

	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
	state = nfs4_do_open(dir, ctx, flags, sattr, ilabel, NULL);
	if (IS_ERR(state)) {
@@ -4229,6 +4232,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir,
		data->arg.attrs = sattr;
		data->arg.ftype = ftype;
		data->arg.bitmask = nfs4_bitmask(server, data->label);
		data->arg.umask = current_umask();
		data->res.server = server;
		data->res.fh = &data->fh;
		data->res.fattr = &data->fattr;
@@ -4326,12 +4330,14 @@ static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr)
{
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs4_exception exception = { };
	struct nfs4_label l, *label = NULL;
	int err;

	label = nfs4_label_init_security(dir, dentry, sattr, &l);

	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
	do {
		err = _nfs4_proc_mkdir(dir, dentry, sattr, label);
@@ -4435,12 +4441,14 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
		struct iattr *sattr, dev_t rdev)
{
	struct nfs_server *server = NFS_SERVER(dir);
	struct nfs4_exception exception = { };
	struct nfs4_label l, *label = NULL;
	int err;

	label = nfs4_label_init_security(dir, dentry, sattr, &l);

	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		sattr->ia_mode &= ~current_umask();
	do {
		err = _nfs4_proc_mknod(dir, dentry, sattr, label, rdev);
+24 −12
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
#include <linux/nfs.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/fs_struct.h>

#include "nfs4_fs.h"
#include "internal.h"
@@ -1008,7 +1009,7 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
				const struct nfs4_label *label,
				const struct nfs_server *server,
				bool excl_check)
				bool excl_check, const umode_t *umask)
{
	char owner_name[IDMAP_NAMESZ];
	char owner_group[IDMAP_NAMESZ];
@@ -1022,19 +1023,22 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,

	/*
	 * We reserve enough space to write the entire attribute buffer at once.
	 * In the worst-case, this would be
	 * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
	 * = 40 bytes, plus any contribution from variable-length fields
	 *            such as owner/group.
	 */
	if (iap->ia_valid & ATTR_SIZE) {
		bmval[0] |= FATTR4_WORD0_SIZE;
		len += 8;
	}
	if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
		umask = NULL;
	if (iap->ia_valid & ATTR_MODE) {
		if (umask) {
			bmval[2] |= FATTR4_WORD2_MODE_UMASK;
			len += 8;
		} else {
			bmval[1] |= FATTR4_WORD1_MODE;
			len += 4;
		}
	}
	if (iap->ia_valid & ATTR_UID) {
		owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
		if (owner_namelen < 0) {
@@ -1134,6 +1138,10 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
		*p++ = cpu_to_be32(label->len);
		p = xdr_encode_opaque_fixed(p, label->label, label->len);
	}
	if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
		*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
		*p++ = cpu_to_be32(*umask);
	}

/* out: */
}
@@ -1188,7 +1196,8 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
	}

	encode_string(xdr, create->name->len, create->name->name);
	encode_attrs(xdr, create->attrs, create->label, create->server, false);
	encode_attrs(xdr, create->attrs, create->label, create->server, false,
		     &create->umask);
}

static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
@@ -1408,11 +1417,13 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
	switch(arg->createmode) {
	case NFS4_CREATE_UNCHECKED:
		*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false);
		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
			     &arg->umask);
		break;
	case NFS4_CREATE_GUARDED:
		*p = cpu_to_be32(NFS4_CREATE_GUARDED);
		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false);
		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
			     &arg->umask);
		break;
	case NFS4_CREATE_EXCLUSIVE:
		*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
@@ -1421,7 +1432,8 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
	case NFS4_CREATE_EXCLUSIVE4_1:
		*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
		encode_nfs4_verifier(xdr, &arg->u.verifier);
		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true);
		encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true,
			     &arg->umask);
	}
}

@@ -1677,7 +1689,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
{
	encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
	encode_nfs4_stateid(xdr, &arg->stateid);
	encode_attrs(xdr, arg->iap, arg->label, server, false);
	encode_attrs(xdr, arg->iap, arg->label, server, false, NULL);
}

static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
+1 −0
Original line number Diff line number Diff line
@@ -440,6 +440,7 @@ enum lock_type4 {
#define FATTR4_WORD2_MDSTHRESHOLD       (1UL << 4)
#define FATTR4_WORD2_CLONE_BLKSIZE	(1UL << 13)
#define FATTR4_WORD2_SECURITY_LABEL     (1UL << 16)
#define FATTR4_WORD2_MODE_UMASK		(1UL << 17)

/* MDS threshold bitmap bits */
#define THRESHOLD_RD                    (1UL << 0)
+2 −0
Original line number Diff line number Diff line
@@ -433,6 +433,7 @@ struct nfs_openargs {
	enum open_claim_type4	claim;
	enum createmode4	createmode;
	const struct nfs4_label *label;
	umode_t			umask;
};

struct nfs_openres {
@@ -958,6 +959,7 @@ struct nfs4_create_arg {
	const struct nfs_fh *		dir_fh;
	const u32 *			bitmask;
	const struct nfs4_label		*label;
	umode_t				umask;
};

struct nfs4_create_res {