diff --git a/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch b/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch new file mode 100644 index 000000000..610ec0113 --- /dev/null +++ b/NFSv4-Save-the-owner-group-name-string-when-doing-op.patch @@ -0,0 +1,605 @@ +ommit 6926afd1925a54a13684ebe05987868890665e2b +Author: Trond Myklebust +Date: Sat Jan 7 13:22:46 2012 -0500 + + NFSv4: Save the owner/group name string when doing open + + ...so that we can do the uid/gid mapping outside the asynchronous RPC + context. + This fixes a bug in the current NFSv4 atomic open code where the client + isn't able to determine what the true uid/gid fields of the file are, + (because the asynchronous nature of the OPEN call denies it the ability + to do an upcall) and so fills them with default values, marking the + inode as needing revalidation. + Unfortunately, in some cases, the VFS will do some additional sanity + checks on the file, and may override the server's decision to allow + the open because it sees the wrong owner/group fields. + + Signed-off-by: Trond Myklebust + +diff -up linux-3.2.noarch/fs/nfs/idmap.c.orig linux-3.2.noarch/fs/nfs/idmap.c +--- linux-3.2.noarch/fs/nfs/idmap.c.orig 2012-03-15 10:38:58.876578000 -0400 ++++ linux-3.2.noarch/fs/nfs/idmap.c 2012-03-15 10:51:10.344228000 -0400 +@@ -38,6 +38,89 @@ + #include + #include + #include ++#include ++ ++/** ++ * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields ++ * @fattr: fully initialised struct nfs_fattr ++ * @owner_name: owner name string cache ++ * @group_name: group name string cache ++ */ ++void nfs_fattr_init_names(struct nfs_fattr *fattr, ++ struct nfs4_string *owner_name, ++ struct nfs4_string *group_name) ++{ ++ fattr->owner_name = owner_name; ++ fattr->group_name = group_name; ++} ++ ++static void nfs_fattr_free_owner_name(struct nfs_fattr *fattr) ++{ ++ fattr->valid &= ~NFS_ATTR_FATTR_OWNER_NAME; ++ kfree(fattr->owner_name->data); ++} ++ ++static void nfs_fattr_free_group_name(struct nfs_fattr *fattr) ++{ ++ fattr->valid &= ~NFS_ATTR_FATTR_GROUP_NAME; ++ kfree(fattr->group_name->data); ++} ++ ++static bool nfs_fattr_map_owner_name(struct nfs_server *server, struct nfs_fattr *fattr) ++{ ++ struct nfs4_string *owner = fattr->owner_name; ++ __u32 uid; ++ ++ if (!(fattr->valid & NFS_ATTR_FATTR_OWNER_NAME)) ++ return false; ++ if (nfs_map_name_to_uid(server, owner->data, owner->len, &uid) == 0) { ++ fattr->uid = uid; ++ fattr->valid |= NFS_ATTR_FATTR_OWNER; ++ } ++ return true; ++} ++ ++static bool nfs_fattr_map_group_name(struct nfs_server *server, struct nfs_fattr *fattr) ++{ ++ struct nfs4_string *group = fattr->group_name; ++ __u32 gid; ++ ++ if (!(fattr->valid & NFS_ATTR_FATTR_GROUP_NAME)) ++ return false; ++ if (nfs_map_group_to_gid(server, group->data, group->len, &gid) == 0) { ++ fattr->gid = gid; ++ fattr->valid |= NFS_ATTR_FATTR_GROUP; ++ } ++ return true; ++} ++ ++/** ++ * nfs_fattr_free_names - free up the NFSv4 owner and group strings ++ * @fattr: a fully initialised nfs_fattr structure ++ */ ++void nfs_fattr_free_names(struct nfs_fattr *fattr) ++{ ++ if (fattr->valid & NFS_ATTR_FATTR_OWNER_NAME) ++ nfs_fattr_free_owner_name(fattr); ++ if (fattr->valid & NFS_ATTR_FATTR_GROUP_NAME) ++ nfs_fattr_free_group_name(fattr); ++} ++ ++/** ++ * nfs_fattr_map_and_free_names - map owner/group strings into uid/gid and free ++ * @server: pointer to the filesystem nfs_server structure ++ * @fattr: a fully initialised nfs_fattr structure ++ * ++ * This helper maps the cached NFSv4 owner/group strings in fattr into ++ * their numeric uid/gid equivalents, and then frees the cached strings. ++ */ ++void nfs_fattr_map_and_free_names(struct nfs_server *server, struct nfs_fattr *fattr) ++{ ++ if (nfs_fattr_map_owner_name(server, fattr)) ++ nfs_fattr_free_owner_name(fattr); ++ if (nfs_fattr_map_group_name(server, fattr)) ++ nfs_fattr_free_group_name(fattr); ++} + + static int nfs_map_string_to_numeric(const char *name, size_t namelen, __u32 *res) + { +diff -up linux-3.2.noarch/fs/nfs/inode.c.orig linux-3.2.noarch/fs/nfs/inode.c +--- linux-3.2.noarch/fs/nfs/inode.c.orig 2012-03-15 10:39:00.362624000 -0400 ++++ linux-3.2.noarch/fs/nfs/inode.c 2012-03-15 10:51:10.352227000 -0400 +@@ -1020,6 +1020,8 @@ void nfs_fattr_init(struct nfs_fattr *fa + fattr->valid = 0; + fattr->time_start = jiffies; + fattr->gencount = nfs_inc_attr_generation_counter(); ++ fattr->owner_name = NULL; ++ fattr->group_name = NULL; + } + + struct nfs_fattr *nfs_alloc_fattr(void) +diff -up linux-3.2.noarch/fs/nfs/nfs4proc.c.orig linux-3.2.noarch/fs/nfs/nfs4proc.c +--- linux-3.2.noarch/fs/nfs/nfs4proc.c.orig 2012-03-15 10:39:00.380629000 -0400 ++++ linux-3.2.noarch/fs/nfs/nfs4proc.c 2012-03-15 10:51:10.362231000 -0400 +@@ -52,6 +52,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -765,6 +766,8 @@ struct nfs4_opendata { + struct nfs_openres o_res; + struct nfs_open_confirmargs c_arg; + struct nfs_open_confirmres c_res; ++ struct nfs4_string owner_name; ++ struct nfs4_string group_name; + struct nfs_fattr f_attr; + struct nfs_fattr dir_attr; + struct dentry *dir; +@@ -788,6 +791,7 @@ static void nfs4_init_opendata_res(struc + p->o_res.server = p->o_arg.server; + nfs_fattr_init(&p->f_attr); + nfs_fattr_init(&p->dir_attr); ++ nfs_fattr_init_names(&p->f_attr, &p->owner_name, &p->group_name); + } + + static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, +@@ -819,6 +823,7 @@ static struct nfs4_opendata *nfs4_openda + p->o_arg.name = &dentry->d_name; + p->o_arg.server = server; + p->o_arg.bitmask = server->attr_bitmask; ++ p->o_arg.dir_bitmask = server->cache_consistency_bitmask; + p->o_arg.claim = NFS4_OPEN_CLAIM_NULL; + if (flags & O_CREAT) { + u32 *s; +@@ -855,6 +860,7 @@ static void nfs4_opendata_free(struct kr + dput(p->dir); + dput(p->dentry); + nfs_sb_deactive(sb); ++ nfs_fattr_free_names(&p->f_attr); + kfree(p); + } + +@@ -1579,6 +1585,8 @@ static int _nfs4_recover_proc_open(struc + if (status != 0 || !data->rpc_done) + return status; + ++ nfs_fattr_map_and_free_names(NFS_SERVER(dir), &data->f_attr); ++ + nfs_refresh_inode(dir, o_res->dir_attr); + + if (o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) { +@@ -1611,6 +1619,8 @@ static int _nfs4_proc_open(struct nfs4_o + return status; + } + ++ nfs_fattr_map_and_free_names(server, &data->f_attr); ++ + if (o_arg->open_flags & O_CREAT) { + update_changeattr(dir, &o_res->cinfo); + nfs_post_op_update_inode(dir, o_res->dir_attr); +diff -up linux-3.2.noarch/fs/nfs/nfs4xdr.c.orig linux-3.2.noarch/fs/nfs/nfs4xdr.c +--- linux-3.2.noarch/fs/nfs/nfs4xdr.c.orig 2012-03-15 10:38:54.054438000 -0400 ++++ linux-3.2.noarch/fs/nfs/nfs4xdr.c 2012-03-15 10:51:10.373231000 -0400 +@@ -2298,7 +2298,7 @@ static void nfs4_xdr_enc_open(struct rpc + encode_getfh(xdr, &hdr); + encode_getfattr(xdr, args->bitmask, &hdr); + encode_restorefh(xdr, &hdr); +- encode_getfattr(xdr, args->bitmask, &hdr); ++ encode_getfattr(xdr, args->dir_bitmask, &hdr); + encode_nops(&hdr); + } + +@@ -3791,7 +3791,8 @@ out_overflow: + } + + static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, +- const struct nfs_server *server, uint32_t *uid, int may_sleep) ++ const struct nfs_server *server, uint32_t *uid, ++ struct nfs4_string *owner_name) + { + uint32_t len; + __be32 *p; +@@ -3808,8 +3809,12 @@ static int decode_attr_owner(struct xdr_ + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + goto out_overflow; +- if (!may_sleep) { +- /* do nothing */ ++ if (owner_name != NULL) { ++ owner_name->data = kmemdup(p, len, GFP_NOWAIT); ++ if (owner_name->data != NULL) { ++ owner_name->len = len; ++ ret = NFS_ATTR_FATTR_OWNER_NAME; ++ } + } else if (len < XDR_MAX_NETOBJ) { + if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0) + ret = NFS_ATTR_FATTR_OWNER; +@@ -3829,7 +3834,8 @@ out_overflow: + } + + static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, +- const struct nfs_server *server, uint32_t *gid, int may_sleep) ++ const struct nfs_server *server, uint32_t *gid, ++ struct nfs4_string *group_name) + { + uint32_t len; + __be32 *p; +@@ -3846,8 +3852,12 @@ static int decode_attr_group(struct xdr_ + p = xdr_inline_decode(xdr, len); + if (unlikely(!p)) + goto out_overflow; +- if (!may_sleep) { +- /* do nothing */ ++ if (group_name != NULL) { ++ group_name->data = kmemdup(p, len, GFP_NOWAIT); ++ if (group_name->data != NULL) { ++ group_name->len = len; ++ ret = NFS_ATTR_FATTR_GROUP_NAME; ++ } + } else if (len < XDR_MAX_NETOBJ) { + if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0) + ret = NFS_ATTR_FATTR_GROUP; +@@ -4284,7 +4294,7 @@ xdr_error: + + static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, + struct nfs_fattr *fattr, struct nfs_fh *fh, +- const struct nfs_server *server, int may_sleep) ++ const struct nfs_server *server) + { + int status; + umode_t fmode = 0; +@@ -4351,12 +4361,12 @@ static int decode_getfattr_attrs(struct + goto xdr_error; + fattr->valid |= status; + +- status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, may_sleep); ++ status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name); + if (status < 0) + goto xdr_error; + fattr->valid |= status; + +- status = decode_attr_group(xdr, bitmap, server, &fattr->gid, may_sleep); ++ status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name); + if (status < 0) + goto xdr_error; + fattr->valid |= status; +@@ -4397,7 +4407,7 @@ xdr_error: + } + + static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, +- struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) ++ struct nfs_fh *fh, const struct nfs_server *server) + { + __be32 *savep; + uint32_t attrlen, +@@ -4416,7 +4426,7 @@ static int decode_getfattr_generic(struc + if (status < 0) + goto xdr_error; + +- status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); ++ status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server); + if (status < 0) + goto xdr_error; + +@@ -4427,9 +4437,9 @@ xdr_error: + } + + static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, +- const struct nfs_server *server, int may_sleep) ++ const struct nfs_server *server) + { +- return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); ++ return decode_getfattr_generic(xdr, fattr, NULL, server); + } + + /* +@@ -5710,8 +5720,7 @@ static int nfs4_xdr_dec_open_downgrade(s + status = decode_open_downgrade(xdr, res); + if (status != 0) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5737,8 +5746,7 @@ static int nfs4_xdr_dec_access(struct rp + status = decode_access(xdr, res); + if (status != 0) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5767,8 +5775,7 @@ static int nfs4_xdr_dec_lookup(struct rp + status = decode_getfh(xdr, res->fh); + if (status) + goto out; +- status = decode_getfattr(xdr, res->fattr, res->server +- ,!RPC_IS_ASYNC(rqstp->rq_task)); ++ status = decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5794,8 +5801,7 @@ static int nfs4_xdr_dec_lookup_root(stru + goto out; + status = decode_getfh(xdr, res->fh); + if (status == 0) +- status = decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ status = decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5821,8 +5827,7 @@ static int nfs4_xdr_dec_remove(struct rp + status = decode_remove(xdr, &res->cinfo); + if (status) + goto out; +- decode_getfattr(xdr, res->dir_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->dir_attr, res->server); + out: + return status; + } +@@ -5855,14 +5860,12 @@ static int nfs4_xdr_dec_rename(struct rp + if (status) + goto out; + /* Current FH is target directory */ +- if (decode_getfattr(xdr, res->new_fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->new_fattr, res->server)) + goto out; + status = decode_restorefh(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->old_fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->old_fattr, res->server); + out: + return status; + } +@@ -5898,14 +5901,12 @@ static int nfs4_xdr_dec_link(struct rpc_ + * Note order: OP_LINK leaves the directory as the current + * filehandle. + */ +- if (decode_getfattr(xdr, res->dir_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->dir_attr, res->server)) + goto out; + status = decode_restorefh(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -5937,14 +5938,12 @@ static int nfs4_xdr_dec_create(struct rp + status = decode_getfh(xdr, res->fh); + if (status) + goto out; +- if (decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->fattr, res->server)) + goto out; + status = decode_restorefh(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->dir_fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->dir_fattr, res->server); + out: + return status; + } +@@ -5976,8 +5975,7 @@ static int nfs4_xdr_dec_getattr(struct r + status = decode_putfh(xdr); + if (status) + goto out; +- status = decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ status = decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6079,8 +6077,7 @@ static int nfs4_xdr_dec_close(struct rpc + * an ESTALE error. Shouldn't be a problem, + * though, since fattr->valid will remain unset. + */ +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6111,13 +6108,11 @@ static int nfs4_xdr_dec_open(struct rpc_ + goto out; + if (decode_getfh(xdr, &res->fh) != 0) + goto out; +- if (decode_getfattr(xdr, res->f_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)) != 0) ++ if (decode_getfattr(xdr, res->f_attr, res->server) != 0) + goto out; + if (decode_restorefh(xdr) != 0) + goto out; +- decode_getfattr(xdr, res->dir_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->dir_attr, res->server); + out: + return status; + } +@@ -6165,8 +6160,7 @@ static int nfs4_xdr_dec_open_noattr(stru + status = decode_open(xdr, res); + if (status) + goto out; +- decode_getfattr(xdr, res->f_attr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->f_attr, res->server); + out: + return status; + } +@@ -6193,8 +6187,7 @@ static int nfs4_xdr_dec_setattr(struct r + status = decode_setattr(xdr); + if (status) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6374,8 +6367,7 @@ static int nfs4_xdr_dec_write(struct rpc + if (status) + goto out; + if (res->fattr) +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + if (!status) + status = res->count; + out: +@@ -6404,8 +6396,7 @@ static int nfs4_xdr_dec_commit(struct rp + if (status) + goto out; + if (res->fattr) +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6564,8 +6555,7 @@ static int nfs4_xdr_dec_delegreturn(stru + status = decode_delegreturn(xdr); + if (status != 0) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6594,8 +6584,7 @@ static int nfs4_xdr_dec_fs_locations(str + goto out; + xdr_enter_page(xdr, PAGE_SIZE); + status = decode_getfattr(xdr, &res->fs_locations->fattr, +- res->fs_locations->server, +- !RPC_IS_ASYNC(req->rq_task)); ++ res->fs_locations->server); + out: + return status; + } +@@ -6844,8 +6833,7 @@ static int nfs4_xdr_dec_layoutcommit(str + status = decode_layoutcommit(xdr, rqstp, res); + if (status) + goto out; +- decode_getfattr(xdr, res->fattr, res->server, +- !RPC_IS_ASYNC(rqstp->rq_task)); ++ decode_getfattr(xdr, res->fattr, res->server); + out: + return status; + } +@@ -6976,7 +6964,7 @@ int nfs4_decode_dirent(struct xdr_stream + goto out_overflow; + + if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, +- entry->server, 1) < 0) ++ entry->server) < 0) + goto out_overflow; + if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) + entry->ino = entry->fattr->mounted_on_fileid; +diff -up linux-3.2.noarch/include/linux/nfs_idmap.h.orig linux-3.2.noarch/include/linux/nfs_idmap.h +--- linux-3.2.noarch/include/linux/nfs_idmap.h.orig 2012-01-04 18:55:44.000000000 -0500 ++++ linux-3.2.noarch/include/linux/nfs_idmap.h 2012-03-15 10:51:10.395228000 -0400 +@@ -66,6 +66,8 @@ struct idmap_msg { + /* Forward declaration to make this header independent of others */ + struct nfs_client; + struct nfs_server; ++struct nfs_fattr; ++struct nfs4_string; + + #ifdef CONFIG_NFS_USE_NEW_IDMAPPER + +@@ -97,6 +99,12 @@ void nfs_idmap_delete(struct nfs_client + + #endif /* CONFIG_NFS_USE_NEW_IDMAPPER */ + ++void nfs_fattr_init_names(struct nfs_fattr *fattr, ++ struct nfs4_string *owner_name, ++ struct nfs4_string *group_name); ++void nfs_fattr_free_names(struct nfs_fattr *); ++void nfs_fattr_map_and_free_names(struct nfs_server *, struct nfs_fattr *); ++ + int nfs_map_name_to_uid(const struct nfs_server *, const char *, size_t, __u32 *); + int nfs_map_group_to_gid(const struct nfs_server *, const char *, size_t, __u32 *); + int nfs_map_uid_to_name(const struct nfs_server *, __u32, char *, size_t); +diff -up linux-3.2.noarch/include/linux/nfs_xdr.h.orig linux-3.2.noarch/include/linux/nfs_xdr.h +--- linux-3.2.noarch/include/linux/nfs_xdr.h.orig 2012-03-15 10:38:54.464449000 -0400 ++++ linux-3.2.noarch/include/linux/nfs_xdr.h 2012-03-15 10:51:10.415229000 -0400 +@@ -18,6 +18,11 @@ + /* Forward declaration for NFS v3 */ + struct nfs4_secinfo_flavors; + ++struct nfs4_string { ++ unsigned int len; ++ char *data; ++}; ++ + struct nfs_fsid { + uint64_t major; + uint64_t minor; +@@ -61,6 +66,8 @@ struct nfs_fattr { + struct timespec pre_ctime; /* pre_op_attr.ctime */ + unsigned long time_start; + unsigned long gencount; ++ struct nfs4_string *owner_name; ++ struct nfs4_string *group_name; + }; + + #define NFS_ATTR_FATTR_TYPE (1U << 0) +@@ -85,6 +92,8 @@ struct nfs_fattr { + #define NFS_ATTR_FATTR_V4_REFERRAL (1U << 19) /* NFSv4 referral */ + #define NFS_ATTR_FATTR_MOUNTPOINT (1U << 20) /* Treat as mountpoint */ + #define NFS_ATTR_FATTR_MOUNTED_ON_FILEID (1U << 21) ++#define NFS_ATTR_FATTR_OWNER_NAME (1U << 22) ++#define NFS_ATTR_FATTR_GROUP_NAME (1U << 23) + + #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \ + | NFS_ATTR_FATTR_MODE \ +@@ -324,6 +333,7 @@ struct nfs_openargs { + const struct qstr * name; + const struct nfs_server *server; /* Needed for ID mapping */ + const u32 * bitmask; ++ const u32 * dir_bitmask; + __u32 claim; + struct nfs4_sequence_args seq_args; + }; +@@ -342,6 +352,8 @@ struct nfs_openres { + __u32 do_recall; + __u64 maxsize; + __u32 attrset[NFS4_BITMAP_SIZE]; ++ struct nfs4_string *owner; ++ struct nfs4_string *group_owner; + struct nfs4_sequence_res seq_res; + }; + +@@ -778,11 +790,6 @@ struct nfs3_getaclres { + struct posix_acl * acl_default; + }; + +-struct nfs4_string { +- unsigned int len; +- char *data; +-}; +- + #ifdef CONFIG_NFS_V4 + + typedef u64 clientid4; diff --git a/SHLIB_BASE-randomization.patch b/SHLIB_BASE-randomization.patch new file mode 100644 index 000000000..80e4d644b --- /dev/null +++ b/SHLIB_BASE-randomization.patch @@ -0,0 +1,69 @@ +diff -uNrp kernel-3.2.fc16.orig/arch/x86/mm/mmap.c kernel-3.2.fc16.new/arch/x86/mm/mmap.c +--- kernel-3.2.fc16.orig/arch/x86/mm/mmap.c 2012-03-19 16:47:03.495169091 -0400 ++++ kernel-3.2.fc16.new/arch/x86/mm/mmap.c 2012-03-19 16:50:03.574168052 -0400 +@@ -106,6 +106,10 @@ static unsigned long mmap_legacy_base(vo + return TASK_UNMAPPED_BASE + mmap_rnd(); + } + ++#ifdef CONFIG_X86_32 ++ #define SHLIB_BASE 0x00111000 ++#endif ++ + /* + * This function, called very early during the creation of a new + * process VM image, sets up which VM layout function to use: +@@ -126,8 +126,10 @@ void arch_pick_mmap_layout(struct mm_str + #ifdef CONFIG_X86_32 + if (!(current->personality & READ_IMPLIES_EXEC) + && !(__supported_pte_mask & _PAGE_NX) +- && mmap_is_ia32()) ++ && mmap_is_ia32()) { ++ mm->shlib_base = SHLIB_BASE + mmap_rnd(); + mm->get_unmapped_exec_area = arch_get_unmapped_exec_area; ++ } + #endif + mm->unmap_area = arch_unmap_area_topdown; + } +diff -uNrp kernel-3.2.fc16.orig/include/linux/mm_types.h kernel-3.2.fc16.new/include/linux/mm_types.h +--- kernel-3.2.fc16.orig/include/linux/mm_types.h 2012-03-19 16:46:47.382169153 -0400 ++++ kernel-3.2.fc16.new/include/linux/mm_types.h 2012-03-19 16:50:40.738168219 -0400 +@@ -300,6 +300,7 @@ struct mm_struct { + void (*unmap_area) (struct mm_struct *mm, unsigned long addr); + #endif + unsigned long mmap_base; /* base of mmap area */ ++ unsigned long shlib_base; /* base of lib map area (ASCII armour)*/ + unsigned long task_size; /* size of task vm space */ + unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */ + unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */ +diff -uNrp kernel-3.2.fc16.orig/mm/mmap.c kernel-3.2.fc16.new/mm/mmap.c +--- kernel-3.2.fc16.orig/mm/mmap.c 2012-03-19 16:46:15.791169274 -0400 ++++ kernel-3.2.fc16.new/mm/mmap.c 2012-03-19 16:51:37.351166875 -0400 +@@ -1594,8 +1594,6 @@ static bool should_randomize(void) + !(current->personality & ADDR_NO_RANDOMIZE); + } + +-#define SHLIB_BASE 0x00110000 +- + unsigned long + arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0, + unsigned long len0, unsigned long pgoff, unsigned long flags) +@@ -1612,8 +1610,8 @@ arch_get_unmapped_exec_area(struct file + return addr; + + if (!addr) +- addr = !should_randomize() ? SHLIB_BASE : +- randomize_range(SHLIB_BASE, 0x01000000, len); ++ addr = !should_randomize() ? mm->shlib_base : ++ randomize_range(mm->shlib_base, 0x01000000, len); + + if (addr) { + addr = PAGE_ALIGN(addr); +@@ -1623,7 +1621,7 @@ arch_get_unmapped_exec_area(struct file + return addr; + } + +- addr = SHLIB_BASE; ++ addr = mm->shlib_base; + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) diff --git a/kernel.spec b/kernel.spec index fd5f6075c..e28ce9288 100644 --- a/kernel.spec +++ b/kernel.spec @@ -42,7 +42,7 @@ Summary: The Linux kernel # When changing real_sublevel below, reset this by hand to 1 # (or to 0 and then use rpmdev-bumpspec). # -%global baserelease 4 +%global baserelease 1 %global fedora_build %{baserelease} # real_sublevel is the 3.x kernel version we're starting with @@ -51,7 +51,7 @@ Summary: The Linux kernel %define fake_sublevel %(echo $((40 + %{real_sublevel}))) # Do we have a -stable update to apply? -%define stable_update 10 +%define stable_update 12 # Is it a -stable RC? %define stable_rc 0 # Set rpm version accordingly @@ -639,6 +639,7 @@ Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 Patch4000: NFSv4-Reduce-the-footprint-of-the-idmapper.patch Patch4001: NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +Patch4003: NFSv4-Save-the-owner-group-name-string-when-doing-op.patch # patches headed upstream @@ -703,7 +704,6 @@ Patch21092: e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 #Patch21093: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -Patch21093: scsi-fix-sd_revalidate_disk-oops.patch #rhbz 771058 Patch21100: msi-irq-sysfs-warning.patch @@ -720,6 +720,9 @@ Patch21104: sony-laptop-Enable-keyboard-backlight-by-default.patch #rhbz 803809 CVE-2012-1179 Patch21106: mm-thp-fix-pmd_bad-triggering.patch +#rhbz 804947 CVE-2012-1568 +Patch21107: SHLIB_BASE-randomization.patch + Patch21110: x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch Patch21200: unhandled-irqs-switch-to-polling.patch @@ -1178,6 +1181,7 @@ ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch # NFSv4 ApplyPatch NFSv4-Reduce-the-footprint-of-the-idmapper.patch ApplyPatch NFSv4-Further-reduce-the-footprint-of-the-idmapper.patch +ApplyPatch NFSv4-Save-the-owner-group-name-string-when-doing-op.patch # USB @@ -1323,7 +1327,6 @@ ApplyPatch e1000e-Avoid-wrong-check-on-TX-hang.patch #rhbz 754518 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch -ApplyPatch scsi-fix-sd_revalidate_disk-oops.patch # Remove overlap between bcma/b43 and brcmsmac and reenable bcm4331 ApplyPatch bcma-brcmsmac-compat.patch @@ -1343,6 +1346,9 @@ ApplyPatch x86-ioapic-add-register-checks-for-bogus-io-apic-entries.patch #rhbz 803809 CVE-2012-1179 ApplyPatch mm-thp-fix-pmd_bad-triggering.patch +#rhbz 804947 CVE-2012-1568 +ApplyPatch SHLIB_BASE-randomization.patch + # END OF PATCH APPLICATIONS %endif @@ -1990,6 +1996,13 @@ fi # and build. %changelog +* Tue Mar 20 2012 Justin M. Forbes 2.6.42.12-1 +- Linux 3.2.10 +- CVE-2012-1568 SHLIB_BASE randomization (rhbz 804947) + +* Mon Mar 19 2012 Steve Dickson +- NFSv4: Save the owner/group name string when doing open (bz 794780) + * Fri Mar 16 2012 Justin M. Forbes - re-enable threading on hibernate compression/decompression diff --git a/scsi-fix-sd_revalidate_disk-oops.patch b/scsi-fix-sd_revalidate_disk-oops.patch deleted file mode 100644 index defa240a2..000000000 --- a/scsi-fix-sd_revalidate_disk-oops.patch +++ /dev/null @@ -1,116 +0,0 @@ ---- linux-2.6.42.noarch/fs/partitions/check.c~ 2012-02-20 18:32:55.314253719 -0500 -+++ linux-2.6.42.noarch/fs/partitions/check.c 2012-02-20 18:34:46.509859745 -0500 -@@ -539,17 +539,11 @@ static bool disk_unlock_native_capacity( - } - } - --int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -+static int drop_partitions(struct gendisk *disk, struct block_device *bdev) - { -- struct parsed_partitions *state = NULL; - struct disk_part_iter piter; - struct hd_struct *part; -- int p, highest, res; --rescan: -- if (state && !IS_ERR(state)) { -- kfree(state); -- state = NULL; -- } -+ int res; - - if (bdev->bd_part_count) - return -EBUSY; -@@ -562,6 +556,24 @@ rescan: - delete_partition(disk, part->partno); - disk_part_iter_exit(&piter); - -+ return 0; -+} -+ -+int rescan_partitions(struct gendisk *disk, struct block_device *bdev) -+{ -+ struct parsed_partitions *state = NULL; -+ struct hd_struct *part; -+ int p, highest, res; -+rescan: -+ if (state && !IS_ERR(state)) { -+ kfree(state); -+ state = NULL; -+ } -+ -+ res = drop_partitions(disk, bdev); -+ if (res) -+ return res; -+ - if (disk->fops->revalidate_disk) - disk->fops->revalidate_disk(disk); - check_disk_size_change(disk, bdev); -@@ -665,6 +677,26 @@ rescan: - return 0; - } - -+int invalidate_partitions(struct gendisk *disk, struct block_device *bdev) -+{ -+ int res; -+ -+ if (!bdev->bd_invalidated) -+ return 0; -+ -+ res = drop_partitions(disk, bdev); -+ if (res) -+ return res; -+ -+ set_capacity(disk, 0); -+ check_disk_size_change(disk, bdev); -+ bdev->bd_invalidated = 0; -+ /* tell userspace that the media / partition table may have changed */ -+ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); -+ -+ return 0; -+} -+ - unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) - { - struct address_space *mapping = bdev->bd_inode->i_mapping; ---- linux-2.6.42.noarch/include/linux/genhd.h~ 2012-02-20 18:35:02.777802107 -0500 -+++ linux-2.6.42.noarch/include/linux/genhd.h 2012-02-20 18:35:13.873762792 -0500 -@@ -596,6 +596,7 @@ extern char *disk_name (struct gendisk * - - extern int disk_expand_part_tbl(struct gendisk *disk, int target); - extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); -+extern int invalidate_partitions(struct gendisk *disk, struct block_device *bdev); - extern struct hd_struct * __must_check add_partition(struct gendisk *disk, - int partno, sector_t start, - sector_t len, int flags, ---- linux-2.6.42.noarch/fs/block_dev.c~ 2012-02-20 18:35:24.890723757 -0500 -+++ linux-2.6.42.noarch/fs/block_dev.c 2012-02-20 18:36:25.166510197 -0500 -@@ -1159,8 +1159,12 @@ static int __blkdev_get(struct block_dev - * The latter is necessary to prevent ghost - * partitions on a removed medium. - */ -- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) -- rescan_partitions(disk, bdev); -+ if (bdev->bd_invalidated) { -+ if (!ret) -+ rescan_partitions(disk, bdev); -+ else if (ret == -ENOMEDIUM) -+ invalidate_partitions(disk, bdev); -+ } - if (ret) - goto out_clear; - } else { -@@ -1190,8 +1194,12 @@ static int __blkdev_get(struct block_dev - if (bdev->bd_disk->fops->open) - ret = bdev->bd_disk->fops->open(bdev, mode); - /* the same as first opener case, read comment there */ -- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM)) -- rescan_partitions(bdev->bd_disk, bdev); -+ if (bdev->bd_invalidated) { -+ if (!ret) -+ rescan_partitions(bdev->bd_disk, bdev); -+ else if (ret == -ENOMEDIUM) -+ invalidate_partitions(bdev->bd_disk, bdev); -+ } - if (ret) - goto out_unlock_bdev; - } diff --git a/sources b/sources index a003ef5f5..02f08ef39 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ 364066fa18767ec0ae5f4e4abcf9dc51 linux-3.2.tar.xz -7481fa09f2efda915ed19a9da33a2e59 patch-3.2.10.xz +ee0ce13f2cb7f03a8cda0910fd0fa050 patch-3.2.12.xz