diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-08 11:49:24 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-08 11:49:24 -0500 |
| commit | 9446389ef612096704fdf18fa79bab423d4110f0 (patch) | |
| tree | 3e4fda7270be58ae176d20d318e61fb115b325b5 /fs/nfs | |
| parent | cdd0972945dbcb8ea24db365d9b0e100af2a27bb (diff) | |
| parent | 84c6f6046c5a2189160a8f0dca8b90427bf690ea (diff) | |
Merge commit 'origin' into devel
Diffstat (limited to 'fs/nfs')
| -rw-r--r-- | fs/nfs/dir.c | 2 | ||||
| -rw-r--r-- | fs/nfs/inode.c | 6 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 3 | ||||
| -rw-r--r-- | fs/nfs/super.c | 64 |
4 files changed, 71 insertions, 4 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index ae04892a5e5d..6cea7479c5b4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -710,6 +710,8 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | |||
| 710 | { | 710 | { |
| 711 | struct nfs_server *server = NFS_SERVER(inode); | 711 | struct nfs_server *server = NFS_SERVER(inode); |
| 712 | 712 | ||
| 713 | if (test_bit(NFS_INO_MOUNTPOINT, &NFS_I(inode)->flags)) | ||
| 714 | return 0; | ||
| 713 | if (nd != NULL) { | 715 | if (nd != NULL) { |
| 714 | /* VFS wants an on-the-wire revalidation */ | 716 | /* VFS wants an on-the-wire revalidation */ |
| 715 | if (nd->flags & LOOKUP_REVAL) | 717 | if (nd->flags & LOOKUP_REVAL) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 36cb99985d22..c49f6d8b42d2 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -299,6 +299,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 299 | else | 299 | else |
| 300 | inode->i_op = &nfs_mountpoint_inode_operations; | 300 | inode->i_op = &nfs_mountpoint_inode_operations; |
| 301 | inode->i_fop = NULL; | 301 | inode->i_fop = NULL; |
| 302 | set_bit(NFS_INO_MOUNTPOINT, &nfsi->flags); | ||
| 302 | } | 303 | } |
| 303 | } else if (S_ISLNK(inode->i_mode)) | 304 | } else if (S_ISLNK(inode->i_mode)) |
| 304 | inode->i_op = &nfs_symlink_inode_operations; | 305 | inode->i_op = &nfs_symlink_inode_operations; |
| @@ -1007,8 +1008,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1007 | 1008 | ||
| 1008 | server = NFS_SERVER(inode); | 1009 | server = NFS_SERVER(inode); |
| 1009 | /* Update the fsid? */ | 1010 | /* Update the fsid? */ |
| 1010 | if (S_ISDIR(inode->i_mode) | 1011 | if (S_ISDIR(inode->i_mode) && |
| 1011 | && !nfs_fsid_equal(&server->fsid, &fattr->fsid)) | 1012 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
| 1013 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | ||
| 1012 | server->fsid = fattr->fsid; | 1014 | server->fsid = fattr->fsid; |
| 1013 | 1015 | ||
| 1014 | /* | 1016 | /* |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 985dc2931031..4c1122a13844 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #include <linux/mount.h> | 5 | #include <linux/mount.h> |
| 6 | #include <linux/security.h> | ||
| 6 | 7 | ||
| 7 | struct nfs_string; | 8 | struct nfs_string; |
| 8 | 9 | ||
| @@ -57,6 +58,8 @@ struct nfs_parsed_mount_data { | |||
| 57 | char *export_path; | 58 | char *export_path; |
| 58 | int protocol; | 59 | int protocol; |
| 59 | } nfs_server; | 60 | } nfs_server; |
| 61 | |||
| 62 | struct security_mnt_opts lsm_opts; | ||
| 60 | }; | 63 | }; |
| 61 | 64 | ||
| 62 | /* client.c */ | 65 | /* client.c */ |
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, | |||
| 684 | static int nfs_parse_mount_options(char *raw, | 684 | static 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, | |||
| 1042 | out_nomem: | 1057 | out_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 | 1060 | out_security_failure: | |
| 1061 | free_secdata(secdata); | ||
| 1062 | printk(KERN_INFO "NFS: security options invalid: %d\n", rc); | ||
| 1063 | return 0; | ||
| 1046 | out_unrec_vers: | 1064 | out_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, | |||
| 1523 | out: | 1574 | out: |
| 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 | ||
| 1528 | out_err_nosb: | 1580 | out_err_nosb: |
| 1529 | nfs_free_server(server); | 1581 | nfs_free_server(server); |
| 1530 | goto out; | 1582 | goto out; |
| 1531 | 1583 | ||
| 1584 | error_splat_root: | ||
| 1585 | dput(mntroot); | ||
| 1532 | error_splat_super: | 1586 | error_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 | ||
| 1903 | out_free: | 1963 | out_free: |
