Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
authorDavid S. Miller <davem@davemloft.net>
Tue, 18 Mar 2008 06:44:31 +0000 (23:44 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Mar 2008 06:44:31 +0000 (23:44 -0700)
1  2 
fs/nfs/super.c

diff --combined fs/nfs/super.c
index bdcf6d3ef62f3ddb69d6355272c7484e48c1ac8f,fcf4b982c88580bca2d841d13c8e00e75f281627..dd4dfcd632ec76aa78c1c2e603c88a4e4401644a
@@@ -632,7 -632,7 +632,7 @@@ static int nfs_verify_server_address(st
        switch (addr->sa_family) {
        case AF_INET: {
                struct sockaddr_in *sa = (struct sockaddr_in *)addr;
 -              return sa->sin_addr.s_addr != INADDR_ANY;
 +              return sa->sin_addr.s_addr != htonl(INADDR_ANY);
        }
        case AF_INET6: {
                struct in6_addr *sa = &((struct sockaddr_in6 *)addr)->sin6_addr;
@@@ -684,8 -684,9 +684,9 @@@ static void nfs_parse_server_address(ch
  static int nfs_parse_mount_options(char *raw,
                                   struct nfs_parsed_mount_data *mnt)
  {
-       char *p, *string;
+       char *p, *string, *secdata;
        unsigned short port = 0;
+       int rc;
  
        if (!raw) {
                dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
        }
        dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
  
+       secdata = alloc_secdata();
+       if (!secdata)
+               goto out_nomem;
+       rc = security_sb_copy_data(raw, secdata);
+       if (rc)
+               goto out_security_failure;
+       rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts);
+       if (rc)
+               goto out_security_failure;
+       free_secdata(secdata);
        while ((p = strsep(&raw, ",")) != NULL) {
                substring_t args[MAX_OPT_ARGS];
                int option, token;
  out_nomem:
        printk(KERN_INFO "NFS: not enough memory to parse option\n");
        return 0;
+ out_security_failure:
+       free_secdata(secdata);
+       printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
+       return 0;
  out_unrec_vers:
        printk(KERN_INFO "NFS: unrecognized NFS version number\n");
        return 0;
@@@ -1214,6 -1232,33 +1232,33 @@@ static int nfs_validate_mount_data(voi
                args->namlen            = data->namlen;
                args->bsize             = data->bsize;
                args->auth_flavors[0]   = data->pseudoflavor;
+               /*
+                * The legacy version 6 binary mount data from userspace has a
+                * field used only to transport selinux information into the
+                * the kernel.  To continue to support that functionality we
+                * have a touch of selinux knowledge here in the NFS code. The
+                * userspace code converted context=blah to just blah so we are
+                * converting back to the full string selinux understands.
+                */
+               if (data->context[0]){
+ #ifdef CONFIG_SECURITY_SELINUX
+                       int rc;
+                       char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL);
+                       if (!opts_str)
+                               return -ENOMEM;
+                       strcpy(opts_str, "context=");
+                       data->context[NFS_MAX_CONTEXT_LEN] = '\0';
+                       strcat(opts_str, &data->context[0]);
+                       rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts);
+                       kfree(opts_str);
+                       if (rc)
+                               return rc;
+ #else
+                       return -EINVAL;
+ #endif
+               }
                break;
        default: {
                unsigned int len;
@@@ -1476,6 -1521,8 +1521,8 @@@ static int nfs_get_sb(struct file_syste
        };
        int error;
  
+       security_init_mnt_opts(&data.lsm_opts);
        /* Validate the mount data */
        error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name);
        if (error < 0)
                goto error_splat_super;
        }
  
+       error = security_sb_set_mnt_opts(s, &data.lsm_opts);
+       if (error)
+               goto error_splat_root;
        s->s_flags |= MS_ACTIVE;
        mnt->mnt_sb = s;
        mnt->mnt_root = mntroot;
  out:
        kfree(data.nfs_server.hostname);
        kfree(data.mount_server.hostname);
+       security_free_mnt_opts(&data.lsm_opts);
        return error;
  
  out_err_nosb:
        nfs_free_server(server);
        goto out;
  
+ error_splat_root:
+       dput(mntroot);
  error_splat_super:
        up_write(&s->s_umount);
        deactivate_super(s);
@@@ -1608,6 -1662,9 +1662,9 @@@ static int nfs_xdev_get_sb(struct file_
        mnt->mnt_sb = s;
        mnt->mnt_root = mntroot;
  
+       /* clone any lsm security options from the parent to the new sb */
+       security_sb_clone_mnt_opts(data->sb, s);
        dprintk("<-- nfs_xdev_get_sb() = 0\n");
        return 0;
  
@@@ -1850,6 -1907,8 +1907,8 @@@ static int nfs4_get_sb(struct file_syst
        };
        int error;
  
+       security_init_mnt_opts(&data.lsm_opts);
        /* Validate the mount data */
        error = nfs4_validate_mount_data(raw_data, &data, dev_name);
        if (error < 0)
@@@ -1898,6 -1957,7 +1957,7 @@@ out
        kfree(data.client_address);
        kfree(data.nfs_server.export_path);
        kfree(data.nfs_server.hostname);
+       security_free_mnt_opts(&data.lsm_opts);
        return error;
  
  out_free: