diff options
author | Eric Paris <eparis@redhat.com> | 2011-03-03 16:09:14 -0500 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2011-03-03 16:12:28 -0500 |
commit | 026eb167ae77244458fa4b4b9fc171209c079ba7 (patch) | |
tree | 1e66fcfeb0b43a6fb764e1d07f8f0200d0c99094 | |
parent | ff36fe2c845cab2102e4826c1ffa0a6ebf487c65 (diff) |
SELinux: implement the new sb_remount LSM hook
For SELinux we do not allow security information to change during a remount
operation. Thus this hook simply strips the security module options from
the data and verifies that those are the same options as exist on the
current superblock.
Signed-off-by: Eric Paris <eparis@redhat.com>
Reviewed-by: James Morris <jmorris@namei.org>
-rw-r--r-- | security/selinux/hooks.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 3decf07b8dc1..f2f3cf2e806d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2363,6 +2363,91 @@ out: | |||
2363 | return rc; | 2363 | return rc; |
2364 | } | 2364 | } |
2365 | 2365 | ||
2366 | static int selinux_sb_remount(struct super_block *sb, void *data) | ||
2367 | { | ||
2368 | int rc, i, *flags; | ||
2369 | struct security_mnt_opts opts; | ||
2370 | char *secdata, **mount_options; | ||
2371 | struct superblock_security_struct *sbsec = sb->s_security; | ||
2372 | |||
2373 | if (!(sbsec->flags & SE_SBINITIALIZED)) | ||
2374 | return 0; | ||
2375 | |||
2376 | if (!data) | ||
2377 | return 0; | ||
2378 | |||
2379 | if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) | ||
2380 | return 0; | ||
2381 | |||
2382 | security_init_mnt_opts(&opts); | ||
2383 | secdata = alloc_secdata(); | ||
2384 | if (!secdata) | ||
2385 | return -ENOMEM; | ||
2386 | rc = selinux_sb_copy_data(data, secdata); | ||
2387 | if (rc) | ||
2388 | goto out_free_secdata; | ||
2389 | |||
2390 | rc = selinux_parse_opts_str(secdata, &opts); | ||
2391 | if (rc) | ||
2392 | goto out_free_secdata; | ||
2393 | |||
2394 | mount_options = opts.mnt_opts; | ||
2395 | flags = opts.mnt_opts_flags; | ||
2396 | |||
2397 | for (i = 0; i < opts.num_mnt_opts; i++) { | ||
2398 | u32 sid; | ||
2399 | size_t len; | ||
2400 | |||
2401 | if (flags[i] == SE_SBLABELSUPP) | ||
2402 | continue; | ||
2403 | len = strlen(mount_options[i]); | ||
2404 | rc = security_context_to_sid(mount_options[i], len, &sid); | ||
2405 | if (rc) { | ||
2406 | printk(KERN_WARNING "SELinux: security_context_to_sid" | ||
2407 | "(%s) failed for (dev %s, type %s) errno=%d\n", | ||
2408 | mount_options[i], sb->s_id, sb->s_type->name, rc); | ||
2409 | goto out_free_opts; | ||
2410 | } | ||
2411 | rc = -EINVAL; | ||
2412 | switch (flags[i]) { | ||
2413 | case FSCONTEXT_MNT: | ||
2414 | if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) | ||
2415 | goto out_bad_option; | ||
2416 | break; | ||
2417 | case CONTEXT_MNT: | ||
2418 | if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) | ||
2419 | goto out_bad_option; | ||
2420 | break; | ||
2421 | case ROOTCONTEXT_MNT: { | ||
2422 | struct inode_security_struct *root_isec; | ||
2423 | root_isec = sb->s_root->d_inode->i_security; | ||
2424 | |||
2425 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) | ||
2426 | goto out_bad_option; | ||
2427 | break; | ||
2428 | } | ||
2429 | case DEFCONTEXT_MNT: | ||
2430 | if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) | ||
2431 | goto out_bad_option; | ||
2432 | break; | ||
2433 | default: | ||
2434 | goto out_free_opts; | ||
2435 | } | ||
2436 | } | ||
2437 | |||
2438 | rc = 0; | ||
2439 | out_free_opts: | ||
2440 | security_free_mnt_opts(&opts); | ||
2441 | out_free_secdata: | ||
2442 | free_secdata(secdata); | ||
2443 | return rc; | ||
2444 | out_bad_option: | ||
2445 | printk(KERN_WARNING "SELinux: unable to change security options " | ||
2446 | "during remount (dev %s, type=%s)\n", sb->s_id, | ||
2447 | sb->s_type->name); | ||
2448 | goto out_free_opts; | ||
2449 | } | ||
2450 | |||
2366 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2451 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2367 | { | 2452 | { |
2368 | const struct cred *cred = current_cred(); | 2453 | const struct cred *cred = current_cred(); |
@@ -5356,6 +5441,7 @@ static struct security_operations selinux_ops = { | |||
5356 | .sb_alloc_security = selinux_sb_alloc_security, | 5441 | .sb_alloc_security = selinux_sb_alloc_security, |
5357 | .sb_free_security = selinux_sb_free_security, | 5442 | .sb_free_security = selinux_sb_free_security, |
5358 | .sb_copy_data = selinux_sb_copy_data, | 5443 | .sb_copy_data = selinux_sb_copy_data, |
5444 | .sb_remount = selinux_sb_remount, | ||
5359 | .sb_kern_mount = selinux_sb_kern_mount, | 5445 | .sb_kern_mount = selinux_sb_kern_mount, |
5360 | .sb_show_options = selinux_sb_show_options, | 5446 | .sb_show_options = selinux_sb_show_options, |
5361 | .sb_statfs = selinux_sb_statfs, | 5447 | .sb_statfs = selinux_sb_statfs, |