Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2013 16:36:19 +0000 (09:36 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2013 16:36:19 +0000 (09:36 -0700)
Pull key management race fix from James Morris.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  keys: fix race with concurrent install_user_keyrings()

fs/pipe.c
net/ceph/osdmap.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/xprtsock.c

index 64a494cef0a00be57d0800637b71caf2537c2694..2234f3f61f8d8fbc6a1f77dbaae6412130b8a5d4 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -863,6 +863,9 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
        int ret = -ENOENT;
 
+       if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
+               return -EINVAL;
+
        mutex_lock(&inode->i_mutex);
 
        if (inode->i_pipe) {
index 69bc4bf89e3e79bb47eddcac63367913a8645ef0..4543b9aba40ce1a9e4565824624bcecba6c298cb 100644 (file)
@@ -654,6 +654,24 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)
        return 0;
 }
 
+static int __decode_pgid(void **p, void *end, struct ceph_pg *pg)
+{
+       u8 v;
+
+       ceph_decode_need(p, end, 1+8+4+4, bad);
+       v = ceph_decode_8(p);
+       if (v != 1)
+               goto bad;
+       pg->pool = ceph_decode_64(p);
+       pg->seed = ceph_decode_32(p);
+       *p += 4; /* skip preferred */
+       return 0;
+
+bad:
+       dout("error decoding pgid\n");
+       return -EINVAL;
+}
+
 /*
  * decode a full map.
  */
@@ -745,13 +763,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
        for (i = 0; i < len; i++) {
                int n, j;
                struct ceph_pg pgid;
-               struct ceph_pg_v1 pgid_v1;
                struct ceph_pg_mapping *pg;
 
-               ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad);
-               ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1));
-               pgid.pool = le32_to_cpu(pgid_v1.pool);
-               pgid.seed = le16_to_cpu(pgid_v1.ps);
+               err = __decode_pgid(p, end, &pgid);
+               if (err)
+                       goto bad;
+               ceph_decode_need(p, end, sizeof(u32), bad);
                n = ceph_decode_32(p);
                err = -EINVAL;
                if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
@@ -818,8 +835,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
        u16 version;
 
        ceph_decode_16_safe(p, end, version, bad);
-       if (version > 6) {
-               pr_warning("got unknown v %d > %d of inc osdmap\n", version, 6);
+       if (version != 6) {
+               pr_warning("got unknown v %d != 6 of inc osdmap\n", version);
                goto bad;
        }
 
@@ -963,15 +980,14 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
        while (len--) {
                struct ceph_pg_mapping *pg;
                int j;
-               struct ceph_pg_v1 pgid_v1;
                struct ceph_pg pgid;
                u32 pglen;
-               ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
-               ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1));
-               pgid.pool = le32_to_cpu(pgid_v1.pool);
-               pgid.seed = le16_to_cpu(pgid_v1.ps);
-               pglen = ceph_decode_32(p);
 
+               err = __decode_pgid(p, end, &pgid);
+               if (err)
+                       goto bad;
+               ceph_decode_need(p, end, sizeof(u32), bad);
+               pglen = ceph_decode_32(p);
                if (pglen) {
                        ceph_decode_need(p, end, pglen*sizeof(u32), bad);
 
index f7d34e7b6f818ba52bec46795b83062cbdf5a71e..5ead60550895f848ba2348bba3bbbfc50ddea7ea 100644 (file)
@@ -447,17 +447,21 @@ static int rsc_parse(struct cache_detail *cd,
        else {
                int N, i;
 
+               /*
+                * NOTE: we skip uid_valid()/gid_valid() checks here:
+                * instead, * -1 id's are later mapped to the
+                * (export-specific) anonymous id by nfsd_setuser.
+                *
+                * (But supplementary gid's get no such special
+                * treatment so are checked for validity here.)
+                */
                /* uid */
                rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
-               if (!uid_valid(rsci.cred.cr_uid))
-                       goto out;
 
                /* gid */
                if (get_int(&mesg, &id))
                        goto out;
                rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
-               if (!gid_valid(rsci.cred.cr_gid))
-                       goto out;
 
                /* number of additional gid's */
                if (get_int(&mesg, &N))
index c1d8476b76929b4300d967dd795aa6c2ce38f7a0..3d02130828da671066b40aa7dd769cf6a7bd4a74 100644 (file)
@@ -849,6 +849,14 @@ static void xs_tcp_close(struct rpc_xprt *xprt)
                xs_tcp_shutdown(xprt);
 }
 
+static void xs_local_destroy(struct rpc_xprt *xprt)
+{
+       xs_close(xprt);
+       xs_free_peer_addresses(xprt);
+       xprt_free(xprt);
+       module_put(THIS_MODULE);
+}
+
 /**
  * xs_destroy - prepare to shutdown a transport
  * @xprt: doomed transport
@@ -862,10 +870,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
 
        cancel_delayed_work_sync(&transport->connect_worker);
 
-       xs_close(xprt);
-       xs_free_peer_addresses(xprt);
-       xprt_free(xprt);
-       module_put(THIS_MODULE);
+       xs_local_destroy(xprt);
 }
 
 static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@ -2482,7 +2487,7 @@ static struct rpc_xprt_ops xs_local_ops = {
        .send_request           = xs_local_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
        .close                  = xs_close,
-       .destroy                = xs_destroy,
+       .destroy                = xs_local_destroy,
        .print_stats            = xs_local_print_stats,
 };