diff options
Diffstat (limited to 'security/selinux')
-rw-r--r-- | security/selinux/hooks.c | 116 | ||||
-rw-r--r-- | security/selinux/include/security.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 5 |
3 files changed, 105 insertions, 18 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5c6f2cd2d095..c956390a9136 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/syslog.h> | 81 | #include <linux/syslog.h> |
82 | #include <linux/user_namespace.h> | 82 | #include <linux/user_namespace.h> |
83 | #include <linux/export.h> | 83 | #include <linux/export.h> |
84 | #include <linux/security.h> | ||
84 | #include <linux/msg.h> | 85 | #include <linux/msg.h> |
85 | #include <linux/shm.h> | 86 | #include <linux/shm.h> |
86 | 87 | ||
@@ -284,13 +285,14 @@ static void superblock_free_security(struct super_block *sb) | |||
284 | 285 | ||
285 | /* The file system's label must be initialized prior to use. */ | 286 | /* The file system's label must be initialized prior to use. */ |
286 | 287 | ||
287 | static const char *labeling_behaviors[6] = { | 288 | static const char *labeling_behaviors[7] = { |
288 | "uses xattr", | 289 | "uses xattr", |
289 | "uses transition SIDs", | 290 | "uses transition SIDs", |
290 | "uses task SIDs", | 291 | "uses task SIDs", |
291 | "uses genfs_contexts", | 292 | "uses genfs_contexts", |
292 | "not configured for labeling", | 293 | "not configured for labeling", |
293 | "uses mountpoint labeling", | 294 | "uses mountpoint labeling", |
295 | "uses native labeling", | ||
294 | }; | 296 | }; |
295 | 297 | ||
296 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); | 298 | static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry); |
@@ -552,7 +554,9 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, | |||
552 | * labeling information. | 554 | * labeling information. |
553 | */ | 555 | */ |
554 | static int selinux_set_mnt_opts(struct super_block *sb, | 556 | static int selinux_set_mnt_opts(struct super_block *sb, |
555 | struct security_mnt_opts *opts) | 557 | struct security_mnt_opts *opts, |
558 | unsigned long kern_flags, | ||
559 | unsigned long *set_kern_flags) | ||
556 | { | 560 | { |
557 | const struct cred *cred = current_cred(); | 561 | const struct cred *cred = current_cred(); |
558 | int rc = 0, i; | 562 | int rc = 0, i; |
@@ -580,6 +584,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
580 | "before the security server is initialized\n"); | 584 | "before the security server is initialized\n"); |
581 | goto out; | 585 | goto out; |
582 | } | 586 | } |
587 | if (kern_flags && !set_kern_flags) { | ||
588 | /* Specifying internal flags without providing a place to | ||
589 | * place the results is not allowed */ | ||
590 | rc = -EINVAL; | ||
591 | goto out; | ||
592 | } | ||
583 | 593 | ||
584 | /* | 594 | /* |
585 | * Binary mount data FS will come through this function twice. Once | 595 | * Binary mount data FS will come through this function twice. Once |
@@ -670,14 +680,21 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
670 | if (strcmp(sb->s_type->name, "proc") == 0) | 680 | if (strcmp(sb->s_type->name, "proc") == 0) |
671 | sbsec->flags |= SE_SBPROC; | 681 | sbsec->flags |= SE_SBPROC; |
672 | 682 | ||
673 | /* Determine the labeling behavior to use for this filesystem type. */ | 683 | if (!sbsec->behavior) { |
674 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? "proc" : sb->s_type->name, &sbsec->behavior, &sbsec->sid); | 684 | /* |
675 | if (rc) { | 685 | * Determine the labeling behavior to use for this |
676 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | 686 | * filesystem type. |
677 | __func__, sb->s_type->name, rc); | 687 | */ |
678 | goto out; | 688 | rc = security_fs_use((sbsec->flags & SE_SBPROC) ? |
689 | "proc" : sb->s_type->name, | ||
690 | &sbsec->behavior, &sbsec->sid); | ||
691 | if (rc) { | ||
692 | printk(KERN_WARNING | ||
693 | "%s: security_fs_use(%s) returned %d\n", | ||
694 | __func__, sb->s_type->name, rc); | ||
695 | goto out; | ||
696 | } | ||
679 | } | 697 | } |
680 | |||
681 | /* sets the context of the superblock for the fs being mounted. */ | 698 | /* sets the context of the superblock for the fs being mounted. */ |
682 | if (fscontext_sid) { | 699 | if (fscontext_sid) { |
683 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); | 700 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred); |
@@ -692,6 +709,11 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
692 | * sets the label used on all file below the mountpoint, and will set | 709 | * sets the label used on all file below the mountpoint, and will set |
693 | * the superblock context if not already set. | 710 | * the superblock context if not already set. |
694 | */ | 711 | */ |
712 | if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) { | ||
713 | sbsec->behavior = SECURITY_FS_USE_NATIVE; | ||
714 | *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS; | ||
715 | } | ||
716 | |||
695 | if (context_sid) { | 717 | if (context_sid) { |
696 | if (!fscontext_sid) { | 718 | if (!fscontext_sid) { |
697 | rc = may_context_mount_sb_relabel(context_sid, sbsec, | 719 | rc = may_context_mount_sb_relabel(context_sid, sbsec, |
@@ -723,7 +745,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
723 | } | 745 | } |
724 | 746 | ||
725 | if (defcontext_sid) { | 747 | if (defcontext_sid) { |
726 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { | 748 | if (sbsec->behavior != SECURITY_FS_USE_XATTR && |
749 | sbsec->behavior != SECURITY_FS_USE_NATIVE) { | ||
727 | rc = -EINVAL; | 750 | rc = -EINVAL; |
728 | printk(KERN_WARNING "SELinux: defcontext option is " | 751 | printk(KERN_WARNING "SELinux: defcontext option is " |
729 | "invalid for this filesystem type\n"); | 752 | "invalid for this filesystem type\n"); |
@@ -980,7 +1003,7 @@ static int superblock_doinit(struct super_block *sb, void *data) | |||
980 | goto out_err; | 1003 | goto out_err; |
981 | 1004 | ||
982 | out: | 1005 | out: |
983 | rc = selinux_set_mnt_opts(sb, &opts); | 1006 | rc = selinux_set_mnt_opts(sb, &opts, 0, NULL); |
984 | 1007 | ||
985 | out_err: | 1008 | out_err: |
986 | security_free_mnt_opts(&opts); | 1009 | security_free_mnt_opts(&opts); |
@@ -1222,6 +1245,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
1222 | } | 1245 | } |
1223 | 1246 | ||
1224 | switch (sbsec->behavior) { | 1247 | switch (sbsec->behavior) { |
1248 | case SECURITY_FS_USE_NATIVE: | ||
1249 | break; | ||
1225 | case SECURITY_FS_USE_XATTR: | 1250 | case SECURITY_FS_USE_XATTR: |
1226 | if (!inode->i_op->getxattr) { | 1251 | if (!inode->i_op->getxattr) { |
1227 | isec->sid = sbsec->def_sid; | 1252 | isec->sid = sbsec->def_sid; |
@@ -1547,6 +1572,18 @@ static inline int path_has_perm(const struct cred *cred, | |||
1547 | return inode_has_perm(cred, inode, av, &ad, 0); | 1572 | return inode_has_perm(cred, inode, av, &ad, 0); |
1548 | } | 1573 | } |
1549 | 1574 | ||
1575 | /* Same as path_has_perm, but uses the inode from the file struct. */ | ||
1576 | static inline int file_path_has_perm(const struct cred *cred, | ||
1577 | struct file *file, | ||
1578 | u32 av) | ||
1579 | { | ||
1580 | struct common_audit_data ad; | ||
1581 | |||
1582 | ad.type = LSM_AUDIT_DATA_PATH; | ||
1583 | ad.u.path = file->f_path; | ||
1584 | return inode_has_perm(cred, file_inode(file), av, &ad, 0); | ||
1585 | } | ||
1586 | |||
1550 | /* Check whether a task can use an open file descriptor to | 1587 | /* Check whether a task can use an open file descriptor to |
1551 | access an inode in a given way. Check access to the | 1588 | access an inode in a given way. Check access to the |
1552 | descriptor itself, and then use dentry_has_perm to | 1589 | descriptor itself, and then use dentry_has_perm to |
@@ -2141,14 +2178,14 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2141 | struct tty_file_private *file_priv; | 2178 | struct tty_file_private *file_priv; |
2142 | 2179 | ||
2143 | /* Revalidate access to controlling tty. | 2180 | /* Revalidate access to controlling tty. |
2144 | Use path_has_perm on the tty path directly rather | 2181 | Use file_path_has_perm on the tty path directly |
2145 | than using file_has_perm, as this particular open | 2182 | rather than using file_has_perm, as this particular |
2146 | file may belong to another process and we are only | 2183 | open file may belong to another process and we are |
2147 | interested in the inode-based check here. */ | 2184 | only interested in the inode-based check here. */ |
2148 | file_priv = list_first_entry(&tty->tty_files, | 2185 | file_priv = list_first_entry(&tty->tty_files, |
2149 | struct tty_file_private, list); | 2186 | struct tty_file_private, list); |
2150 | file = file_priv->file; | 2187 | file = file_priv->file; |
2151 | if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE)) | 2188 | if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE)) |
2152 | drop_tty = 1; | 2189 | drop_tty = 1; |
2153 | } | 2190 | } |
2154 | spin_unlock(&tty_files_lock); | 2191 | spin_unlock(&tty_files_lock); |
@@ -2515,6 +2552,40 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2515 | inode_free_security(inode); | 2552 | inode_free_security(inode); |
2516 | } | 2553 | } |
2517 | 2554 | ||
2555 | static int selinux_dentry_init_security(struct dentry *dentry, int mode, | ||
2556 | struct qstr *name, void **ctx, | ||
2557 | u32 *ctxlen) | ||
2558 | { | ||
2559 | const struct cred *cred = current_cred(); | ||
2560 | struct task_security_struct *tsec; | ||
2561 | struct inode_security_struct *dsec; | ||
2562 | struct superblock_security_struct *sbsec; | ||
2563 | struct inode *dir = dentry->d_parent->d_inode; | ||
2564 | u32 newsid; | ||
2565 | int rc; | ||
2566 | |||
2567 | tsec = cred->security; | ||
2568 | dsec = dir->i_security; | ||
2569 | sbsec = dir->i_sb->s_security; | ||
2570 | |||
2571 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
2572 | newsid = tsec->create_sid; | ||
2573 | } else { | ||
2574 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
2575 | inode_mode_to_security_class(mode), | ||
2576 | name, | ||
2577 | &newsid); | ||
2578 | if (rc) { | ||
2579 | printk(KERN_WARNING | ||
2580 | "%s: security_transition_sid failed, rc=%d\n", | ||
2581 | __func__, -rc); | ||
2582 | return rc; | ||
2583 | } | ||
2584 | } | ||
2585 | |||
2586 | return security_sid_to_context(newsid, (char **)ctx, ctxlen); | ||
2587 | } | ||
2588 | |||
2518 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | 2589 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
2519 | const struct qstr *qstr, char **name, | 2590 | const struct qstr *qstr, char **name, |
2520 | void **value, size_t *len) | 2591 | void **value, size_t *len) |
@@ -2849,7 +2920,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
2849 | return; | 2920 | return; |
2850 | } | 2921 | } |
2851 | 2922 | ||
2923 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2852 | isec->sid = newsid; | 2924 | isec->sid = newsid; |
2925 | isec->initialized = 1; | ||
2926 | |||
2853 | return; | 2927 | return; |
2854 | } | 2928 | } |
2855 | 2929 | ||
@@ -2937,6 +3011,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2937 | if (rc) | 3011 | if (rc) |
2938 | return rc; | 3012 | return rc; |
2939 | 3013 | ||
3014 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2940 | isec->sid = newsid; | 3015 | isec->sid = newsid; |
2941 | isec->initialized = 1; | 3016 | isec->initialized = 1; |
2942 | return 0; | 3017 | return 0; |
@@ -3259,7 +3334,7 @@ static int selinux_file_open(struct file *file, const struct cred *cred) | |||
3259 | * new inode label or new policy. | 3334 | * new inode label or new policy. |
3260 | * This check is not redundant - do not remove. | 3335 | * This check is not redundant - do not remove. |
3261 | */ | 3336 | */ |
3262 | return path_has_perm(cred, &file->f_path, open_file_to_av(file)); | 3337 | return file_path_has_perm(cred, file, open_file_to_av(file)); |
3263 | } | 3338 | } |
3264 | 3339 | ||
3265 | /* task security operations */ | 3340 | /* task security operations */ |
@@ -5420,6 +5495,11 @@ abort_change: | |||
5420 | return error; | 5495 | return error; |
5421 | } | 5496 | } |
5422 | 5497 | ||
5498 | static int selinux_ismaclabel(const char *name) | ||
5499 | { | ||
5500 | return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0); | ||
5501 | } | ||
5502 | |||
5423 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 5503 | static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
5424 | { | 5504 | { |
5425 | return security_sid_to_context(secid, secdata, seclen); | 5505 | return security_sid_to_context(secid, secdata, seclen); |
@@ -5562,6 +5642,7 @@ static struct security_operations selinux_ops = { | |||
5562 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, | 5642 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, |
5563 | .sb_parse_opts_str = selinux_parse_opts_str, | 5643 | .sb_parse_opts_str = selinux_parse_opts_str, |
5564 | 5644 | ||
5645 | .dentry_init_security = selinux_dentry_init_security, | ||
5565 | 5646 | ||
5566 | .inode_alloc_security = selinux_inode_alloc_security, | 5647 | .inode_alloc_security = selinux_inode_alloc_security, |
5567 | .inode_free_security = selinux_inode_free_security, | 5648 | .inode_free_security = selinux_inode_free_security, |
@@ -5657,6 +5738,7 @@ static struct security_operations selinux_ops = { | |||
5657 | .getprocattr = selinux_getprocattr, | 5738 | .getprocattr = selinux_getprocattr, |
5658 | .setprocattr = selinux_setprocattr, | 5739 | .setprocattr = selinux_setprocattr, |
5659 | 5740 | ||
5741 | .ismaclabel = selinux_ismaclabel, | ||
5660 | .secid_to_secctx = selinux_secid_to_secctx, | 5742 | .secid_to_secctx = selinux_secid_to_secctx, |
5661 | .secctx_to_secid = selinux_secctx_to_secid, | 5743 | .secctx_to_secid = selinux_secctx_to_secid, |
5662 | .release_secctx = selinux_release_secctx, | 5744 | .release_secctx = selinux_release_secctx, |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 6d3885165d14..8fd8e18ea340 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -169,6 +169,8 @@ int security_get_allow_unknown(void); | |||
169 | #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ | 169 | #define SECURITY_FS_USE_GENFS 4 /* use the genfs support */ |
170 | #define SECURITY_FS_USE_NONE 5 /* no labeling support */ | 170 | #define SECURITY_FS_USE_NONE 5 /* no labeling support */ |
171 | #define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ | 171 | #define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */ |
172 | #define SECURITY_FS_USE_NATIVE 7 /* use native label support */ | ||
173 | #define SECURITY_FS_USE_MAX 7 /* Highest SECURITY_FS_USE_XXX */ | ||
172 | 174 | ||
173 | int security_fs_use(const char *fstype, unsigned int *behavior, | 175 | int security_fs_use(const char *fstype, unsigned int *behavior, |
174 | u32 *sid); | 176 | u32 *sid); |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 9cd9b7c661ec..c8adde3aff8f 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -2168,7 +2168,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2168 | 2168 | ||
2169 | rc = -EINVAL; | 2169 | rc = -EINVAL; |
2170 | c->v.behavior = le32_to_cpu(buf[0]); | 2170 | c->v.behavior = le32_to_cpu(buf[0]); |
2171 | if (c->v.behavior > SECURITY_FS_USE_NONE) | 2171 | /* Determined at runtime, not in policy DB. */ |
2172 | if (c->v.behavior == SECURITY_FS_USE_MNTPOINT) | ||
2173 | goto out; | ||
2174 | if (c->v.behavior > SECURITY_FS_USE_MAX) | ||
2172 | goto out; | 2175 | goto out; |
2173 | 2176 | ||
2174 | rc = -ENOMEM; | 2177 | rc = -ENOMEM; |