aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2008-03-05 14:20:18 -0500
committerJames Morris <jmorris@namei.org>2008-03-05 16:40:59 -0500
commitf9c3a3802119a2d30f3e4a69aef30a81e09d0209 (patch)
treee777be38afbbec60e3c366169395b9fca7226540 /fs/nfs/super.c
parente0007529893c1c064be90bd21422ca0da4a0198e (diff)
NFS: use new LSM interfaces to explicitly set mount options
NFS and SELinux worked together previously because SELinux had NFS specific knowledge built in. This design was approved by both groups back in 2004 but the recent NFS changes to use nfs_parsed_mount_data and the usage of nfs_clone_mount_data showed this to be a poor fragile solution. This patch fixes the NFS functionality regression by making use of the new LSM interfaces to allow an FS to explicitly set its own mount options. The explicit setting of mount options is done in the nfs get_sb functions which are called before the generic vfs hooks try to set mount options for filesystems which use text mount data. This does not currently support NFSv4 as that functionality did not exist in previous kernels and thus there is no regression. I will be adding the needed code, which I believe to be the exact same as the v3 code, in nfs4_get_sb for 2.6.26. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 1fb381843650..fcf4b982c885 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -684,8 +684,9 @@ static void nfs_parse_server_address(char *value,
684static int nfs_parse_mount_options(char *raw, 684static int nfs_parse_mount_options(char *raw,
685 struct nfs_parsed_mount_data *mnt) 685 struct nfs_parsed_mount_data *mnt)
686{ 686{
687 char *p, *string; 687 char *p, *string, *secdata;
688 unsigned short port = 0; 688 unsigned short port = 0;
689 int rc;
689 690
690 if (!raw) { 691 if (!raw) {
691 dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); 692 dfprintk(MOUNT, "NFS: mount options string was NULL.\n");
@@ -693,6 +694,20 @@ static int nfs_parse_mount_options(char *raw,
693 } 694 }
694 dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); 695 dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw);
695 696
697 secdata = alloc_secdata();
698 if (!secdata)
699 goto out_nomem;
700
701 rc = security_sb_copy_data(raw, secdata);
702 if (rc)
703 goto out_security_failure;
704
705 rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts);
706 if (rc)
707 goto out_security_failure;
708
709 free_secdata(secdata);
710
696 while ((p = strsep(&raw, ",")) != NULL) { 711 while ((p = strsep(&raw, ",")) != NULL) {
697 substring_t args[MAX_OPT_ARGS]; 712 substring_t args[MAX_OPT_ARGS];
698 int option, token; 713 int option, token;
@@ -1042,7 +1057,10 @@ static int nfs_parse_mount_options(char *raw,
1042out_nomem: 1057out_nomem:
1043 printk(KERN_INFO "NFS: not enough memory to parse option\n"); 1058 printk(KERN_INFO "NFS: not enough memory to parse option\n");
1044 return 0; 1059 return 0;
1045 1060out_security_failure:
1061 free_secdata(secdata);
1062 printk(KERN_INFO "NFS: security options invalid: %d\n", rc);
1063 return 0;
1046out_unrec_vers: 1064out_unrec_vers:
1047 printk(KERN_INFO "NFS: unrecognized NFS version number\n"); 1065 printk(KERN_INFO "NFS: unrecognized NFS version number\n");
1048 return 0; 1066 return 0;
@@ -1214,6 +1232,33 @@ static int nfs_validate_mount_data(void *options,
1214 args->namlen = data->namlen; 1232 args->namlen = data->namlen;
1215 args->bsize = data->bsize; 1233 args->bsize = data->bsize;
1216 args->auth_flavors[0] = data->pseudoflavor; 1234 args->auth_flavors[0] = data->pseudoflavor;
1235
1236 /*
1237 * The legacy version 6 binary mount data from userspace has a
1238 * field used only to transport selinux information into the
1239 * the kernel. To continue to support that functionality we
1240 * have a touch of selinux knowledge here in the NFS code. The
1241 * userspace code converted context=blah to just blah so we are
1242 * converting back to the full string selinux understands.
1243 */
1244 if (data->context[0]){
1245#ifdef CONFIG_SECURITY_SELINUX
1246 int rc;
1247 char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL);
1248 if (!opts_str)
1249 return -ENOMEM;
1250 strcpy(opts_str, "context=");
1251 data->context[NFS_MAX_CONTEXT_LEN] = '\0';
1252 strcat(opts_str, &data->context[0]);
1253 rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts);
1254 kfree(opts_str);
1255 if (rc)
1256 return rc;
1257#else
1258 return -EINVAL;
1259#endif
1260 }
1261
1217 break; 1262 break;
1218 default: { 1263 default: {
1219 unsigned int len; 1264 unsigned int len;
@@ -1476,6 +1521,8 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1476 }; 1521 };
1477 int error; 1522 int error;
1478 1523
1524 security_init_mnt_opts(&data.lsm_opts);
1525
1479 /* Validate the mount data */ 1526 /* Validate the mount data */
1480 error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); 1527 error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name);
1481 if (error < 0) 1528 if (error < 0)
@@ -1515,6 +1562,10 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1515 goto error_splat_super; 1562 goto error_splat_super;
1516 } 1563 }
1517 1564
1565 error = security_sb_set_mnt_opts(s, &data.lsm_opts);
1566 if (error)
1567 goto error_splat_root;
1568
1518 s->s_flags |= MS_ACTIVE; 1569 s->s_flags |= MS_ACTIVE;
1519 mnt->mnt_sb = s; 1570 mnt->mnt_sb = s;
1520 mnt->mnt_root = mntroot; 1571 mnt->mnt_root = mntroot;
@@ -1523,12 +1574,15 @@ static int nfs_get_sb(struct file_system_type *fs_type,
1523out: 1574out:
1524 kfree(data.nfs_server.hostname); 1575 kfree(data.nfs_server.hostname);
1525 kfree(data.mount_server.hostname); 1576 kfree(data.mount_server.hostname);
1577 security_free_mnt_opts(&data.lsm_opts);
1526 return error; 1578 return error;
1527 1579
1528out_err_nosb: 1580out_err_nosb:
1529 nfs_free_server(server); 1581 nfs_free_server(server);
1530 goto out; 1582 goto out;
1531 1583
1584error_splat_root:
1585 dput(mntroot);
1532error_splat_super: 1586error_splat_super:
1533 up_write(&s->s_umount); 1587 up_write(&s->s_umount);
1534 deactivate_super(s); 1588 deactivate_super(s);
@@ -1608,6 +1662,9 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags,
1608 mnt->mnt_sb = s; 1662 mnt->mnt_sb = s;
1609 mnt->mnt_root = mntroot; 1663 mnt->mnt_root = mntroot;
1610 1664
1665 /* clone any lsm security options from the parent to the new sb */
1666 security_sb_clone_mnt_opts(data->sb, s);
1667
1611 dprintk("<-- nfs_xdev_get_sb() = 0\n"); 1668 dprintk("<-- nfs_xdev_get_sb() = 0\n");
1612 return 0; 1669 return 0;
1613 1670
@@ -1850,6 +1907,8 @@ static int nfs4_get_sb(struct file_system_type *fs_type,
1850 }; 1907 };
1851 int error; 1908 int error;
1852 1909
1910 security_init_mnt_opts(&data.lsm_opts);
1911
1853 /* Validate the mount data */ 1912 /* Validate the mount data */
1854 error = nfs4_validate_mount_data(raw_data, &data, dev_name); 1913 error = nfs4_validate_mount_data(raw_data, &data, dev_name);
1855 if (error < 0) 1914 if (error < 0)
@@ -1898,6 +1957,7 @@ out:
1898 kfree(data.client_address); 1957 kfree(data.client_address);
1899 kfree(data.nfs_server.export_path); 1958 kfree(data.nfs_server.export_path);
1900 kfree(data.nfs_server.hostname); 1959 kfree(data.nfs_server.hostname);
1960 security_free_mnt_opts(&data.lsm_opts);
1901 return error; 1961 return error;
1902 1962
1903out_free: 1963out_free: