diff options
Diffstat (limited to 'fs')
75 files changed, 773 insertions, 500 deletions
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index da8eefbe830..afd4724b2d9 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c @@ -74,19 +74,20 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) * */ -static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any) +static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) { struct v9fs_dentry *dent; struct p9_fid *fid, *ret; p9_debug(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n", - dentry->d_name.name, dentry, uid, any); + dentry->d_name.name, dentry, from_kuid(&init_user_ns, uid), + any); dent = (struct v9fs_dentry *) dentry->d_fsdata; ret = NULL; if (dent) { spin_lock(&dent->lock); list_for_each_entry(fid, &dent->fidlist, dlist) { - if (any || fid->uid == uid) { + if (any || uid_eq(fid->uid, uid)) { ret = fid; break; } @@ -126,7 +127,7 @@ err_out: } static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, - uid_t uid, int any) + kuid_t uid, int any) { struct dentry *ds; char **wnames, *uname; @@ -233,7 +234,7 @@ err_out: struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) { - uid_t uid; + kuid_t uid; int any, access; struct v9fs_session_info *v9ses; @@ -253,7 +254,7 @@ struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) break; default: - uid = ~0; + uid = INVALID_UID; any = 0; break; } @@ -272,7 +273,7 @@ struct p9_fid *v9fs_fid_clone(struct dentry *dentry) return ret; } -static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, uid_t uid) +static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, kuid_t uid) { struct p9_fid *fid, *ret; @@ -289,7 +290,7 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) int err; struct p9_fid *fid; - fid = v9fs_fid_clone_with_uid(dentry, 0); + fid = v9fs_fid_clone_with_uid(dentry, GLOBAL_ROOT_UID); if (IS_ERR(fid)) goto error_out; /* diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index d934f04e773..58e6cbce415 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -161,7 +161,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) ret = r; continue; } - v9ses->dfltuid = option; + v9ses->dfltuid = make_kuid(current_user_ns(), option); + if (!uid_valid(v9ses->dfltuid)) { + p9_debug(P9_DEBUG_ERROR, + "uid field, but not a uid?\n"); + ret = -EINVAL; + continue; + } break; case Opt_dfltgid: r = match_int(&args[0], &option); @@ -171,7 +177,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) ret = r; continue; } - v9ses->dfltgid = option; + v9ses->dfltgid = make_kgid(current_user_ns(), option); + if (!gid_valid(v9ses->dfltgid)) { + p9_debug(P9_DEBUG_ERROR, + "gid field, but not a gid?\n"); + ret = -EINVAL; + continue; + } break; case Opt_afid: r = match_int(&args[0], &option); @@ -248,8 +260,9 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) else if (strcmp(s, "client") == 0) { v9ses->flags |= V9FS_ACCESS_CLIENT; } else { + uid_t uid; v9ses->flags |= V9FS_ACCESS_SINGLE; - v9ses->uid = simple_strtoul(s, &e, 10); + uid = simple_strtoul(s, &e, 10); if (*e != '\0') { ret = -EINVAL; pr_info("Unknown access argument %s\n", @@ -257,6 +270,13 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) kfree(s); goto free_and_return; } + v9ses->uid = make_kuid(current_user_ns(), uid); + if (!uid_valid(v9ses->uid)) { + ret = -EINVAL; + pr_info("Uknown uid %s\n", s); + kfree(s); + goto free_and_return; + } } kfree(s); @@ -319,7 +339,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, list_add(&v9ses->slist, &v9fs_sessionlist); spin_unlock(&v9fs_sessionlist_lock); - v9ses->uid = ~0; + v9ses->uid = INVALID_UID; v9ses->dfltuid = V9FS_DEFUID; v9ses->dfltgid = V9FS_DEFGID; @@ -364,7 +384,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->flags &= ~V9FS_ACCESS_MASK; v9ses->flags |= V9FS_ACCESS_ANY; - v9ses->uid = ~0; + v9ses->uid = INVALID_UID; } if (!v9fs_proto_dotl(v9ses) || !((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) { @@ -375,7 +395,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->flags &= ~V9FS_ACL_MASK; } - fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, ~0, + fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, INVALID_UID, v9ses->aname); if (IS_ERR(fid)) { retval = PTR_ERR(fid); @@ -387,7 +407,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE) fid->uid = v9ses->uid; else - fid->uid = ~0; + fid->uid = INVALID_UID; #ifdef CONFIG_9P_FSCACHE /* register the session for caching */ diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 34c59f14a1c..a8e127c8962 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -109,9 +109,9 @@ struct v9fs_session_info { char *uname; /* user name to mount as */ char *aname; /* name of remote hierarchy being mounted */ unsigned int maxdata; /* max data for client interface */ - unsigned int dfltuid; /* default uid/muid for legacy support */ - unsigned int dfltgid; /* default gid for legacy support */ - u32 uid; /* if ACCESS_SINGLE, the uid that has access */ + kuid_t dfltuid; /* default uid/muid for legacy support */ + kgid_t dfltgid; /* default gid for legacy support */ + kuid_t uid; /* if ACCESS_SINGLE, the uid that has access */ struct p9_client *clnt; /* 9p client */ struct list_head slist; /* list of sessions registered with v9fs */ struct backing_dev_info bdi; @@ -165,8 +165,8 @@ extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, #define V9FS_PORT 564 #define V9FS_DEFUSER "nobody" #define V9FS_DEFANAME "" -#define V9FS_DEFUID (-2) -#define V9FS_DEFGID (-2) +#define V9FS_DEFUID KUIDT_INIT(-2) +#define V9FS_DEFGID KGIDT_INIT(-2) static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) { diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 57d017ac68e..b5340c829de 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -225,9 +225,9 @@ v9fs_blank_wstat(struct p9_wstat *wstat) wstat->uid = NULL; wstat->gid = NULL; wstat->muid = NULL; - wstat->n_uid = ~0; - wstat->n_gid = ~0; - wstat->n_muid = ~0; + wstat->n_uid = INVALID_UID; + wstat->n_gid = INVALID_GID; + wstat->n_muid = INVALID_UID; wstat->extension = NULL; } diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 8d24ad66dfb..07f409288d1 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -57,7 +57,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, * group of the new file system object. */ -static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) +static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) { BUG_ON(dir_inode == NULL); @@ -245,7 +245,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, int *opened) { int err = 0; - gid_t gid; + kgid_t gid; umode_t mode; char *name = NULL; struct p9_qid qid; @@ -396,7 +396,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, int err; struct v9fs_session_info *v9ses; struct p9_fid *fid = NULL, *dfid = NULL; - gid_t gid; + kgid_t gid; char *name; umode_t mode; struct inode *inode; @@ -697,7 +697,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, const char *symname) { int err; - gid_t gid; + kgid_t gid; char *name; struct p9_qid qid; struct inode *inode; @@ -837,7 +837,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, dev_t rdev) { int err; - gid_t gid; + kgid_t gid; char *name; umode_t mode; struct v9fs_session_info *v9ses; diff --git a/fs/afs/afs.h b/fs/afs/afs.h index c548aa346f0..3c462ff6db6 100644 --- a/fs/afs/afs.h +++ b/fs/afs/afs.h @@ -119,8 +119,8 @@ struct afs_file_status { u64 size; /* file size */ afs_dataversion_t data_version; /* current data version */ u32 author; /* author ID */ - u32 owner; /* owner ID */ - u32 group; /* group ID */ + kuid_t owner; /* owner ID */ + kgid_t group; /* group ID */ afs_access_t caller_access; /* access rights for authenticated caller */ afs_access_t anon_access; /* access rights for unauthenticated caller */ umode_t mode; /* UNIX mode */ @@ -133,13 +133,6 @@ struct afs_file_status { /* * AFS file status change request */ -struct afs_store_status { - u32 mask; /* which bits of the struct are set */ - u32 mtime_client; /* last time client changed data */ - u32 owner; /* owner ID */ - u32 group; /* group ID */ - umode_t mode; /* UNIX mode */ -}; #define AFS_SET_MTIME 0x01 /* set the mtime */ #define AFS_SET_OWNER 0x02 /* set the owner ID */ diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index b960ff05ea0..c2e930ec288 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -42,6 +42,8 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, umode_t mode; u64 data_version, size; u32 changed = 0; /* becomes non-zero if ctime-type changes seen */ + kuid_t owner; + kgid_t group; #define EXTRACT(DST) \ do { \ @@ -56,7 +58,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, size = ntohl(*bp++); data_version = ntohl(*bp++); EXTRACT(status->author); - EXTRACT(status->owner); + owner = make_kuid(&init_user_ns, ntohl(*bp++)); + changed |= !uid_eq(owner, status->owner); + status->owner = owner; EXTRACT(status->caller_access); /* call ticket dependent */ EXTRACT(status->anon_access); EXTRACT(status->mode); @@ -65,7 +69,9 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, bp++; /* seg size */ status->mtime_client = ntohl(*bp++); status->mtime_server = ntohl(*bp++); - EXTRACT(status->group); + group = make_kgid(&init_user_ns, ntohl(*bp++)); + changed |= !gid_eq(group, status->group); + status->group = group; bp++; /* sync counter */ data_version |= (u64) ntohl(*bp++) << 32; EXTRACT(status->lock_count); @@ -181,12 +187,12 @@ static void xdr_encode_AFS_StoreStatus(__be32 **_bp, struct iattr *attr) if (attr->ia_valid & ATTR_UID) { mask |= AFS_SET_OWNER; - owner = attr->ia_uid; + owner = from_kuid(&init_user_ns, attr->ia_uid); } if (attr->ia_valid & ATTR_GID) { mask |= AFS_SET_GROUP; - group = attr->ia_gid; + group = from_kgid(&init_user_ns, attr->ia_gid); } if (attr->ia_valid & ATTR_MODE) { diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 95cffd38239..789bc253b5f 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -69,7 +69,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) set_nlink(inode, vnode->status.nlink); inode->i_uid = vnode->status.owner; - inode->i_gid = 0; + inode->i_gid = GLOBAL_ROOT_GID; inode->i_size = vnode->status.size; inode->i_ctime.tv_sec = vnode->status.mtime_server; inode->i_ctime.tv_nsec = 0; @@ -175,8 +175,8 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; inode->i_op = &afs_autocell_inode_operations; set_nlink(inode, 2); - inode->i_uid = 0; - inode->i_gid = 0; + inode->i_uid = GLOBAL_ROOT_UID; + inode->i_gid = GLOBAL_ROOT_GID; inode->i_ctime.tv_sec = get_seconds(); inode->i_ctime.tv_nsec = 0; inode->i_atime = inode->i_mtime = inode->i_ctime; diff --git a/fs/afs/super.c b/fs/afs/super.c index 43165009428..7c31ec39957 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -24,6 +24,8 @@ #include <linux/parser.h> #include <linux/statfs.h> #include <linux/sched.h> +#include <linux/nsproxy.h> +#include <net/net_namespace.h> #include "internal.h" #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ @@ -363,6 +365,10 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, memset(¶ms, 0, sizeof(params)); + ret = -EINVAL; + if (current->nsproxy->net_ns != &init_net) + goto error; + /* parse the options and device name */ if (options) { ret = afs_parse_options(¶ms, options, &dev_name); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index a1d9bb30c1b..ae2be696eb5 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -930,7 +930,7 @@ static int send_cap_msg(struct ceph_mds_session *session, u64 size, u64 max_size, struct timespec *mtime, struct timespec *atime, u64 time_warp_seq, - uid_t uid, gid_t gid, umode_t mode, + kuid_t uid, kgid_t gid, umode_t mode, u64 xattr_version, struct ceph_buffer *xattrs_buf, u64 follows) @@ -974,8 +974,8 @@ static int send_cap_msg(struct ceph_mds_session *session, ceph_encode_timespec(&fc->atime, atime); fc->time_warp_seq = cpu_to_le32(time_warp_seq); - fc->uid = cpu_to_le32(uid); - fc->gid = cpu_to_le32(gid); + fc->uid = cpu_to_le32(from_kuid(&init_user_ns, uid)); + fc->gid = cpu_to_le32(from_kgid(&init_user_ns, gid)); fc->mode = cpu_to_le32(mode); fc->xattr_version = cpu_to_le64(xattr_version); @@ -1081,8 +1081,8 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap, struct timespec mtime, atime; int wake = 0; umode_t mode; - uid_t uid; - gid_t gid; + kuid_t uid; + kgid_t gid; struct ceph_mds_session *session; u64 xattr_version = 0; struct ceph_buffer *xattr_blob = NULL; @@ -2359,10 +2359,11 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, if ((issued & CEPH_CAP_AUTH_EXCL) == 0) { inode->i_mode = le32_to_cpu(grant->mode); - inode->i_uid = le32_to_cpu(grant->uid); - inode->i_gid = le32_to_cpu(grant->gid); + inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid)); + inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid)); dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode, - inode->i_uid, inode->i_gid); + from_kuid(&init_user_ns, inode->i_uid), + from_kgid(&init_user_ns, inode->i_gid)); } if ((issued & CEPH_CAP_LINK_EXCL) == 0) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 2971eaa65cd..d45895f4a04 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -612,10 +612,11 @@ static int fill_inode(struct inode *inode, if ((issued & CEPH_CAP_AUTH_EXCL) == 0) { inode->i_mode = le32_to_cpu(info->mode); - inode->i_uid = le32_to_cpu(info->uid); - inode->i_gid = le32_to_cpu(info->gid); + inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid)); + inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid)); dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode, - inode->i_uid, inode->i_gid); + from_kuid(&init_user_ns, inode->i_uid), + from_kgid(&init_user_ns, inode->i_gid)); } if ((issued & CEPH_CAP_LINK_EXCL) == 0) @@ -1565,26 +1566,30 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr) if (ia_valid & ATTR_UID) { dout("setattr %p uid %d -> %d\n", inode, - inode->i_uid, attr->ia_uid); + from_kuid(&init_user_ns, inode->i_uid), + from_kuid(&init_user_ns, attr->ia_uid)); if (issued & CEPH_CAP_AUTH_EXCL) { inode->i_uid = attr->ia_uid; dirtied |= CEPH_CAP_AUTH_EXCL; } else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 || - attr->ia_uid != inode->i_uid) { - req->r_args.setattr.uid = cpu_to_le32(attr->ia_uid); + !uid_eq(attr->ia_uid, inode->i_uid)) { + req->r_args.setattr.uid = cpu_to_le32( + from_kuid(&init_user_ns, attr->ia_uid)); mask |= CEPH_SETATTR_UID; release |= CEPH_CAP_AUTH_SHARED; } } if (ia_valid & ATTR_GID) { dout("setattr %p gid %d -> %d\n", inode, - inode->i_gid, attr->ia_gid); + from_kgid(&init_user_ns, inode->i_gid), + from_kgid(&init_user_ns, attr->ia_gid)); if (issued & CEPH_CAP_AUTH_EXCL) { inode->i_gid = attr->ia_gid; dirtied |= CEPH_CAP_AUTH_EXCL; } else if ((issued & CEPH_CAP_AUTH_SHARED) == 0 || - attr->ia_gid != inode->i_gid) { - req->r_args.setattr.gid = cpu_to_le32(attr->ia_gid); + !gid_eq(attr->ia_gid, inode->i_gid)) { + req->r_args.setattr.gid = cpu_to_le32( + from_kgid(&init_user_ns, attr->ia_gid)); mask |= CEPH_SETATTR_GID; release |= CEPH_CAP_AUTH_SHARED; } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 9165eb8309e..7a3dfe0a9a8 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -1658,8 +1658,8 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, head->mdsmap_epoch = cpu_to_le32(mdsc->mdsmap->m_epoch); head->op = cpu_to_le32(req->r_op); - head->caller_uid = cpu_to |