]> err.no Git - linux-2.6/blobdiff - fs/nfs/super.c
Pull fsys_gettimeofday into release branch
[linux-2.6] / fs / nfs / super.c
index 7f4505f6ac6f55fd49c1a8c07bbb65ce63d41388..f9219024f31aca9fd56962050823d4e46bdbbb37 100644 (file)
@@ -190,6 +190,10 @@ static match_table_t nfs_secflavor_tokens = {
        { Opt_sec_lkeyi, "lkeyi" },
        { Opt_sec_lkeyp, "lkeyp" },
 
+       { Opt_sec_spkm, "spkm3" },
+       { Opt_sec_spkmi, "spkm3i" },
+       { Opt_sec_spkmp, "spkm3p" },
+
        { Opt_sec_err, NULL }
 };
 
@@ -585,8 +589,6 @@ static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags)
        struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb);
        struct rpc_clnt *rpc;
 
-       shrink_submounts(vfsmnt, &nfs_automount_list);
-
        if (!(flags & MNT_FORCE))
                return;
        /* -EIO all pending I/O */
@@ -628,7 +630,7 @@ static int nfs_verify_server_address(struct sockaddr *addr)
        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;
@@ -680,8 +682,9 @@ static void nfs_parse_server_address(char *value,
 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");
@@ -689,6 +692,20 @@ static int nfs_parse_mount_options(char *raw,
        }
        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;
@@ -1038,7 +1055,10 @@ static int nfs_parse_mount_options(char *raw,
 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;
@@ -1210,6 +1230,33 @@ static int nfs_validate_mount_data(void *options,
                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;
@@ -1472,6 +1519,8 @@ static int nfs_get_sb(struct file_system_type *fs_type,
        };
        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)
@@ -1511,6 +1560,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
                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;
@@ -1519,12 +1572,15 @@ static int nfs_get_sb(struct file_system_type *fs_type,
 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);
@@ -1604,6 +1660,9 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
        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;
 
@@ -1846,6 +1905,8 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
        };
        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)
@@ -1894,6 +1955,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: