aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c201
1 files changed, 111 insertions, 90 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 75c2e99bfb81..d39b59cf8a08 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -180,7 +180,7 @@ static int inode_alloc_security(struct inode *inode)
180 struct task_security_struct *tsec = current->security; 180 struct task_security_struct *tsec = current->security;
181 struct inode_security_struct *isec; 181 struct inode_security_struct *isec;
182 182
183 isec = kmem_cache_zalloc(sel_inode_cache, GFP_KERNEL); 183 isec = kmem_cache_zalloc(sel_inode_cache, GFP_NOFS);
184 if (!isec) 184 if (!isec)
185 return -ENOMEM; 185 return -ENOMEM;
186 186
@@ -443,8 +443,7 @@ out:
443 * mount options, or whatever. 443 * mount options, or whatever.
444 */ 444 */
445static int selinux_get_mnt_opts(const struct super_block *sb, 445static int selinux_get_mnt_opts(const struct super_block *sb,
446 char ***mount_options, int **mnt_opts_flags, 446 struct security_mnt_opts *opts)
447 int *num_opts)
448{ 447{
449 int rc = 0, i; 448 int rc = 0, i;
450 struct superblock_security_struct *sbsec = sb->s_security; 449 struct superblock_security_struct *sbsec = sb->s_security;
@@ -452,9 +451,7 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
452 u32 len; 451 u32 len;
453 char tmp; 452 char tmp;
454 453
455 *num_opts = 0; 454 security_init_mnt_opts(opts);
456 *mount_options = NULL;
457 *mnt_opts_flags = NULL;
458 455
459 if (!sbsec->initialized) 456 if (!sbsec->initialized)
460 return -EINVAL; 457 return -EINVAL;
@@ -470,18 +467,18 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
470 /* count the number of mount options for this sb */ 467 /* count the number of mount options for this sb */
471 for (i = 0; i < 8; i++) { 468 for (i = 0; i < 8; i++) {
472 if (tmp & 0x01) 469 if (tmp & 0x01)
473 (*num_opts)++; 470 opts->num_mnt_opts++;
474 tmp >>= 1; 471 tmp >>= 1;
475 } 472 }
476 473
477 *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC); 474 opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
478 if (!*mount_options) { 475 if (!opts->mnt_opts) {
479 rc = -ENOMEM; 476 rc = -ENOMEM;
480 goto out_free; 477 goto out_free;
481 } 478 }
482 479
483 *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC); 480 opts->mnt_opts_flags = kcalloc(opts->num_mnt_opts, sizeof(int), GFP_ATOMIC);
484 if (!*mnt_opts_flags) { 481 if (!opts->mnt_opts_flags) {
485 rc = -ENOMEM; 482 rc = -ENOMEM;
486 goto out_free; 483 goto out_free;
487 } 484 }
@@ -491,22 +488,22 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
491 rc = security_sid_to_context(sbsec->sid, &context, &len); 488 rc = security_sid_to_context(sbsec->sid, &context, &len);
492 if (rc) 489 if (rc)
493 goto out_free; 490 goto out_free;
494 (*mount_options)[i] = context; 491 opts->mnt_opts[i] = context;
495 (*mnt_opts_flags)[i++] = FSCONTEXT_MNT; 492 opts->mnt_opts_flags[i++] = FSCONTEXT_MNT;
496 } 493 }
497 if (sbsec->flags & CONTEXT_MNT) { 494 if (sbsec->flags & CONTEXT_MNT) {
498 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); 495 rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len);
499 if (rc) 496 if (rc)
500 goto out_free; 497 goto out_free;
501 (*mount_options)[i] = context; 498 opts->mnt_opts[i] = context;
502 (*mnt_opts_flags)[i++] = CONTEXT_MNT; 499 opts->mnt_opts_flags[i++] = CONTEXT_MNT;
503 } 500 }
504 if (sbsec->flags & DEFCONTEXT_MNT) { 501 if (sbsec->flags & DEFCONTEXT_MNT) {
505 rc = security_sid_to_context(sbsec->def_sid, &context, &len); 502 rc = security_sid_to_context(sbsec->def_sid, &context, &len);
506 if (rc) 503 if (rc)
507 goto out_free; 504 goto out_free;
508 (*mount_options)[i] = context; 505 opts->mnt_opts[i] = context;
509 (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT; 506 opts->mnt_opts_flags[i++] = DEFCONTEXT_MNT;
510 } 507 }
511 if (sbsec->flags & ROOTCONTEXT_MNT) { 508 if (sbsec->flags & ROOTCONTEXT_MNT) {
512 struct inode *root = sbsec->sb->s_root->d_inode; 509 struct inode *root = sbsec->sb->s_root->d_inode;
@@ -515,24 +512,16 @@ static int selinux_get_mnt_opts(const struct super_block *sb,
515 rc = security_sid_to_context(isec->sid, &context, &len); 512 rc = security_sid_to_context(isec->sid, &context, &len);
516 if (rc) 513 if (rc)
517 goto out_free; 514 goto out_free;
518 (*mount_options)[i] = context; 515 opts->mnt_opts[i] = context;
519 (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT; 516 opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
520 } 517 }
521 518
522 BUG_ON(i != *num_opts); 519 BUG_ON(i != opts->num_mnt_opts);
523 520
524 return 0; 521 return 0;
525 522
526out_free: 523out_free:
527 /* don't leak context string if security_sid_to_context had an error */ 524 security_free_mnt_opts(opts);
528 if (*mount_options && i)
529 for (; i > 0; i--)
530 kfree((*mount_options)[i-1]);
531 kfree(*mount_options);
532 *mount_options = NULL;
533 kfree(*mnt_opts_flags);
534 *mnt_opts_flags = NULL;
535 *num_opts = 0;
536 return rc; 525 return rc;
537} 526}
538 527
@@ -553,12 +542,13 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
553 return 1; 542 return 1;
554 return 0; 543 return 0;
555} 544}
545
556/* 546/*
557 * Allow filesystems with binary mount data to explicitly set mount point 547 * Allow filesystems with binary mount data to explicitly set mount point
558 * labeling information. 548 * labeling information.
559 */ 549 */
560static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, 550static int selinux_set_mnt_opts(struct super_block *sb,
561 int *flags, int num_opts) 551 struct security_mnt_opts *opts)
562{ 552{
563 int rc = 0, i; 553 int rc = 0, i;
564 struct task_security_struct *tsec = current->security; 554 struct task_security_struct *tsec = current->security;
@@ -568,6 +558,9 @@ static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
568 struct inode_security_struct *root_isec = inode->i_security; 558 struct inode_security_struct *root_isec = inode->i_security;
569 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; 559 u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
570 u32 defcontext_sid = 0; 560 u32 defcontext_sid = 0;
561 char **mount_options = opts->mnt_opts;
562 int *flags = opts->mnt_opts_flags;
563 int num_opts = opts->num_mnt_opts;
571 564
572 mutex_lock(&sbsec->lock); 565 mutex_lock(&sbsec->lock);
573 566
@@ -589,6 +582,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
589 } 582 }
590 583
591 /* 584 /*
585 * Binary mount data FS will come through this function twice. Once
586 * from an explicit call and once from the generic calls from the vfs.
587 * Since the generic VFS calls will not contain any security mount data
588 * we need to skip the double mount verification.
589 *
590 * This does open a hole in which we will not notice if the first
591 * mount using this sb set explict options and a second mount using
592 * this sb does not set any security options. (The first options
593 * will be used for both mounts)
594 */
595 if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
596 && (num_opts == 0))
597 goto out;
598
599 /*
592 * parse the mount options, check if they are valid sids. 600 * parse the mount options, check if they are valid sids.
593 * also check if someone is trying to mount the same sb more 601 * also check if someone is trying to mount the same sb more
594 * than once with different security options. 602 * than once with different security options.
@@ -752,13 +760,13 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
752 * this early in the boot process. */ 760 * this early in the boot process. */
753 BUG_ON(!ss_initialized); 761 BUG_ON(!ss_initialized);
754 762
755 /* this might go away sometime down the line if there is a new user
756 * of clone, but for now, nfs better not get here... */
757 BUG_ON(newsbsec->initialized);
758
759 /* how can we clone if the old one wasn't set up?? */ 763 /* how can we clone if the old one wasn't set up?? */
760 BUG_ON(!oldsbsec->initialized); 764 BUG_ON(!oldsbsec->initialized);
761 765
766 /* if fs is reusing a sb, just let its options stand... */
767 if (newsbsec->initialized)
768 return;
769
762 mutex_lock(&newsbsec->lock); 770 mutex_lock(&newsbsec->lock);
763 771
764 newsbsec->flags = oldsbsec->flags; 772 newsbsec->flags = oldsbsec->flags;
@@ -792,43 +800,15 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
792 mutex_unlock(&newsbsec->lock); 800 mutex_unlock(&newsbsec->lock);
793} 801}
794 802
795/* 803static int selinux_parse_opts_str(char *options,
796 * string mount options parsing and call set the sbsec 804 struct security_mnt_opts *opts)
797 */
798static int superblock_doinit(struct super_block *sb, void *data)
799{ 805{
806 char *p;
800 char *context = NULL, *defcontext = NULL; 807 char *context = NULL, *defcontext = NULL;
801 char *fscontext = NULL, *rootcontext = NULL; 808 char *fscontext = NULL, *rootcontext = NULL;
802 int rc = 0; 809 int rc, num_mnt_opts = 0;
803 char *p, *options = data;
804 /* selinux only know about a fixed number of mount options */
805 char *mnt_opts[NUM_SEL_MNT_OPTS];
806 int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0;
807
808 if (!data)
809 goto out;
810
811 /* with the nfs patch this will become a goto out; */
812 if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) {
813 const char *name = sb->s_type->name;
814 /* NFS we understand. */
815 if (!strcmp(name, "nfs")) {
816 struct nfs_mount_data *d = data;
817
818 if (d->version != NFS_MOUNT_VERSION)
819 goto out;
820 810
821 if (d->context[0]) { 811 opts->num_mnt_opts = 0;
822 context = kstrdup(d->context, GFP_KERNEL);
823 if (!context) {
824 rc = -ENOMEM;
825 goto out;
826 }
827 }
828 goto build_flags;
829 } else
830 goto out;
831 }
832 812
833 /* Standard string-based options. */ 813 /* Standard string-based options. */
834 while ((p = strsep(&options, "|")) != NULL) { 814 while ((p = strsep(&options, "|")) != NULL) {
@@ -901,26 +881,37 @@ static int superblock_doinit(struct super_block *sb, void *data)
901 } 881 }
902 } 882 }
903 883
904build_flags: 884 rc = -ENOMEM;
885 opts->mnt_opts = kcalloc(NUM_SEL_MNT_OPTS, sizeof(char *), GFP_ATOMIC);
886 if (!opts->mnt_opts)
887 goto out_err;
888
889 opts->mnt_opts_flags = kcalloc(NUM_SEL_MNT_OPTS, sizeof(int), GFP_ATOMIC);
890 if (!opts->mnt_opts_flags) {
891 kfree(opts->mnt_opts);
892 goto out_err;
893 }
894
905 if (fscontext) { 895 if (fscontext) {
906 mnt_opts[num_mnt_opts] = fscontext; 896 opts->mnt_opts[num_mnt_opts] = fscontext;
907 mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; 897 opts->mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT;
908 } 898 }
909 if (context) { 899 if (context) {
910 mnt_opts[num_mnt_opts] = context; 900 opts->mnt_opts[num_mnt_opts] = context;
911 mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; 901 opts->mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT;
912 } 902 }
913 if (rootcontext) { 903 if (rootcontext) {
914 mnt_opts[num_mnt_opts] = rootcontext; 904 opts->mnt_opts[num_mnt_opts] = rootcontext;
915 mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; 905 opts->mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT;
916 } 906 }
917 if (defcontext) { 907 if (defcontext) {
918 mnt_opts[num_mnt_opts] = defcontext; 908 opts->mnt_opts[num_mnt_opts] = defcontext;
919 mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; 909 opts->mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT;
920 } 910 }
921 911
922out: 912 opts->num_mnt_opts = num_mnt_opts;
923 rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts); 913 return 0;
914
924out_err: 915out_err:
925 kfree(context); 916 kfree(context);
926 kfree(defcontext); 917 kfree(defcontext);
@@ -928,6 +919,33 @@ out_err:
928 kfree(rootcontext); 919 kfree(rootcontext);
929 return rc; 920 return rc;
930} 921}
922/*
923 * string mount options parsing and call set the sbsec
924 */
925static int superblock_doinit(struct super_block *sb, void *data)
926{
927 int rc = 0;
928 char *options = data;
929 struct security_mnt_opts opts;
930
931 security_init_mnt_opts(&opts);
932
933 if (!data)
934 goto out;
935
936 BUG_ON(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA);
937
938 rc = selinux_parse_opts_str(options, &opts);
939 if (rc)
940 goto out_err;
941
942out:
943 rc = selinux_set_mnt_opts(sb, &opts);
944
945out_err:
946 security_free_mnt_opts(&opts);
947 return rc;
948}
931 949
932static inline u16 inode_mode_to_security_class(umode_t mode) 950static inline u16 inode_mode_to_security_class(umode_t mode)
933{ 951{
@@ -1125,7 +1143,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1125 } 1143 }
1126 1144
1127 len = INITCONTEXTLEN; 1145 len = INITCONTEXTLEN;
1128 context = kmalloc(len, GFP_KERNEL); 1146 context = kmalloc(len, GFP_NOFS);
1129 if (!context) { 1147 if (!context) {
1130 rc = -ENOMEM; 1148 rc = -ENOMEM;
1131 dput(dentry); 1149 dput(dentry);
@@ -1143,7 +1161,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1143 } 1161 }
1144 kfree(context); 1162 kfree(context);
1145 len = rc; 1163 len = rc;
1146 context = kmalloc(len, GFP_KERNEL); 1164 context = kmalloc(len, GFP_NOFS);
1147 if (!context) { 1165 if (!context) {
1148 rc = -ENOMEM; 1166 rc = -ENOMEM;
1149 dput(dentry); 1167 dput(dentry);
@@ -1167,7 +1185,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1167 rc = 0; 1185 rc = 0;
1168 } else { 1186 } else {
1169 rc = security_context_to_sid_default(context, rc, &sid, 1187 rc = security_context_to_sid_default(context, rc, &sid,
1170 sbsec->def_sid); 1188 sbsec->def_sid,
1189 GFP_NOFS);
1171 if (rc) { 1190 if (rc) {
1172 printk(KERN_WARNING "%s: context_to_sid(%s) " 1191 printk(KERN_WARNING "%s: context_to_sid(%s) "
1173 "returned %d for dev=%s ino=%ld\n", 1192 "returned %d for dev=%s ino=%ld\n",
@@ -1612,6 +1631,12 @@ static inline u32 file_to_av(struct file *file)
1612 else 1631 else
1613 av |= FILE__WRITE; 1632 av |= FILE__WRITE;
1614 } 1633 }
1634 if (!av) {
1635 /*
1636 * Special file opened with flags 3 for ioctl-only use.
1637 */
1638 av = FILE__IOCTL;
1639 }
1615 1640
1616 return av; 1641 return av;
1617} 1642}
@@ -2253,7 +2278,7 @@ static inline void take_selinux_option(char **to, char *from, int *first,
2253 } 2278 }
2254} 2279}
2255 2280
2256static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void *copy) 2281static int selinux_sb_copy_data(char *orig, char *copy)
2257{ 2282{
2258 int fnosec, fsec, rc = 0; 2283 int fnosec, fsec, rc = 0;
2259 char *in_save, *in_curr, *in_end; 2284 char *in_save, *in_curr, *in_end;
@@ -2263,12 +2288,6 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void
2263 in_curr = orig; 2288 in_curr = orig;
2264 sec_curr = copy; 2289 sec_curr = copy;
2265 2290
2266 /* Binary mount data: just copy */
2267 if (type->fs_flags & FS_BINARY_MOUNTDATA) {
2268 copy_page(sec_curr, in_curr);
2269 goto out;
2270 }
2271
2272 nosec = (char *)get_zeroed_page(GFP_KERNEL); 2291 nosec = (char *)get_zeroed_page(GFP_KERNEL);
2273 if (!nosec) { 2292 if (!nosec) {
2274 rc = -ENOMEM; 2293 rc = -ENOMEM;
@@ -2411,7 +2430,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2411 return -EOPNOTSUPP; 2430 return -EOPNOTSUPP;
2412 2431
2413 if (name) { 2432 if (name) {
2414 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); 2433 namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS);
2415 if (!namep) 2434 if (!namep)
2416 return -ENOMEM; 2435 return -ENOMEM;
2417 *name = namep; 2436 *name = namep;
@@ -5251,6 +5270,8 @@ static struct security_operations selinux_ops = {
5251 .sb_get_mnt_opts = selinux_get_mnt_opts, 5270 .sb_get_mnt_opts = selinux_get_mnt_opts,
5252 .sb_set_mnt_opts = selinux_set_mnt_opts, 5271 .sb_set_mnt_opts = selinux_set_mnt_opts,
5253 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, 5272 .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
5273 .sb_parse_opts_str = selinux_parse_opts_str,
5274
5254 5275
5255 .inode_alloc_security = selinux_inode_alloc_security, 5276 .inode_alloc_security = selinux_inode_alloc_security,
5256 .inode_free_security = selinux_inode_free_security, 5277 .inode_free_security = selinux_inode_free_security,