aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2017-12-11 01:01:08 -0500
committerJames Morris <james.l.morris@oracle.com>2017-12-11 01:01:08 -0500
commitd21bd6898336a7892914d308d5e0868f0b863571 (patch)
treef5f756c25348b5a6c1ce9ddbaa7d1ecd1bef40b0 /security/selinux/hooks.c
parent34d8751fd4ffa34e85ee7e85d34168b3f3f62b42 (diff)
parent50c4c4e268a2d7a3e58ebb698ac74da0de40ae36 (diff)
Sync to v4.15-rc3 for security subsystem developers to work against.
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c215
1 files changed, 183 insertions, 32 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f5d304736852..8644d864e3c1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -85,6 +85,7 @@
85#include <linux/export.h> 85#include <linux/export.h>
86#include <linux/msg.h> 86#include <linux/msg.h>
87#include <linux/shm.h> 87#include <linux/shm.h>
88#include <linux/bpf.h>
88 89
89#include "avc.h" 90#include "avc.h"
90#include "objsec.h" 91#include "objsec.h"
@@ -1814,6 +1815,10 @@ static inline int file_path_has_perm(const struct cred *cred,
1814 return inode_has_perm(cred, file_inode(file), av, &ad); 1815 return inode_has_perm(cred, file_inode(file), av, &ad);
1815} 1816}
1816 1817
1818#ifdef CONFIG_BPF_SYSCALL
1819static int bpf_fd_pass(struct file *file, u32 sid);
1820#endif
1821
1817/* Check whether a task can use an open file descriptor to 1822/* Check whether a task can use an open file descriptor to
1818 access an inode in a given way. Check access to the 1823 access an inode in a given way. Check access to the
1819 descriptor itself, and then use dentry_has_perm to 1824 descriptor itself, and then use dentry_has_perm to
@@ -1844,6 +1849,12 @@ static int file_has_perm(const struct cred *cred,
1844 goto out; 1849 goto out;
1845 } 1850 }
1846 1851
1852#ifdef CONFIG_BPF_SYSCALL
1853 rc = bpf_fd_pass(file, cred_sid(cred));
1854 if (rc)
1855 return rc;
1856#endif
1857
1847 /* av is zero if only checking access to the descriptor. */ 1858 /* av is zero if only checking access to the descriptor. */
1848 rc = 0; 1859 rc = 0;
1849 if (av) 1860 if (av)
@@ -2164,6 +2175,12 @@ static int selinux_binder_transfer_file(struct task_struct *from,
2164 return rc; 2175 return rc;
2165 } 2176 }
2166 2177
2178#ifdef CONFIG_BPF_SYSCALL
2179 rc = bpf_fd_pass(file, sid);
2180 if (rc)
2181 return rc;
2182#endif
2183
2167 if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) 2184 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
2168 return 0; 2185 return 0;
2169 2186
@@ -2918,13 +2935,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2918{ 2935{
2919 const struct task_security_struct *tsec = current_security(); 2936 const struct task_security_struct *tsec = current_security();
2920 struct superblock_security_struct *sbsec; 2937 struct superblock_security_struct *sbsec;
2921 u32 sid, newsid, clen; 2938 u32 newsid, clen;
2922 int rc; 2939 int rc;
2923 char *context; 2940 char *context;
2924 2941
2925 sbsec = dir->i_sb->s_security; 2942 sbsec = dir->i_sb->s_security;
2926 2943
2927 sid = tsec->sid;
2928 newsid = tsec->create_sid; 2944 newsid = tsec->create_sid;
2929 2945
2930 rc = selinux_determine_inode_label(current_security(), 2946 rc = selinux_determine_inode_label(current_security(),
@@ -3124,27 +3140,6 @@ static int selinux_inode_getattr(const struct path *path)
3124 return path_has_perm(current_cred(), path, FILE__GETATTR); 3140 return path_has_perm(current_cred(), path, FILE__GETATTR);
3125} 3141}
3126 3142
3127static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
3128{
3129 const struct cred *cred = current_cred();
3130
3131 if (!strncmp(name, XATTR_SECURITY_PREFIX,
3132 sizeof XATTR_SECURITY_PREFIX - 1)) {
3133 if (!strcmp(name, XATTR_NAME_CAPS)) {
3134 if (!capable(CAP_SETFCAP))
3135 return -EPERM;
3136 } else if (!capable(CAP_SYS_ADMIN)) {
3137 /* A different attribute in the security namespace.
3138 Restrict to administrator. */
3139 return -EPERM;
3140 }
3141 }
3142
3143 /* Not an attribute we recognize, so just check the
3144 ordinary setattr permission. */
3145 return dentry_has_perm(cred, dentry, FILE__SETATTR);
3146}
3147
3148static bool has_cap_mac_admin(bool audit) 3143static bool has_cap_mac_admin(bool audit)
3149{ 3144{
3150 const struct cred *cred = current_cred(); 3145 const struct cred *cred = current_cred();
@@ -3167,8 +3162,15 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3167 u32 newsid, sid = current_sid(); 3162 u32 newsid, sid = current_sid();
3168 int rc = 0; 3163 int rc = 0;
3169 3164
3170 if (strcmp(name, XATTR_NAME_SELINUX)) 3165 if (strcmp(name, XATTR_NAME_SELINUX)) {
3171 return selinux_inode_setotherxattr(dentry, name); 3166 rc = cap_inode_setxattr(dentry, name, value, size, flags);
3167 if (rc)
3168 return rc;
3169
3170 /* Not an attribute we recognize, so just check the
3171 ordinary setattr permission. */
3172 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3173 }
3172 3174
3173 sbsec = inode->i_sb->s_security; 3175 sbsec = inode->i_sb->s_security;
3174 if (!(sbsec->flags & SBLABEL_MNT)) 3176 if (!(sbsec->flags & SBLABEL_MNT))
@@ -3191,18 +3193,17 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
3191 if (!has_cap_mac_admin(true)) { 3193 if (!has_cap_mac_admin(true)) {
3192 struct audit_buffer *ab; 3194 struct audit_buffer *ab;
3193 size_t audit_size; 3195 size_t audit_size;
3194 const char *str;
3195 3196
3196 /* We strip a nul only if it is at the end, otherwise the 3197 /* We strip a nul only if it is at the end, otherwise the
3197 * context contains a nul and we should audit that */ 3198 * context contains a nul and we should audit that */
3198 if (value) { 3199 if (value) {
3199 str = value; 3200 const char *str = value;
3201
3200 if (str[size - 1] == '\0') 3202 if (str[size - 1] == '\0')
3201 audit_size = size - 1; 3203 audit_size = size - 1;
3202 else 3204 else
3203 audit_size = size; 3205 audit_size = size;
3204 } else { 3206 } else {
3205 str = "";
3206 audit_size = 0; 3207 audit_size = 0;
3207 } 3208 }
3208 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR); 3209 ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR);
@@ -3282,8 +3283,15 @@ static int selinux_inode_listxattr(struct dentry *dentry)
3282 3283
3283static int selinux_inode_removexattr(struct dentry *dentry, const char *name) 3284static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
3284{ 3285{
3285 if (strcmp(name, XATTR_NAME_SELINUX)) 3286 if (strcmp(name, XATTR_NAME_SELINUX)) {
3286 return selinux_inode_setotherxattr(dentry, name); 3287 int rc = cap_inode_removexattr(dentry, name);
3288 if (rc)
3289 return rc;
3290
3291 /* Not an attribute we recognize, so just check the
3292 ordinary setattr permission. */
3293 return dentry_has_perm(current_cred(), dentry, FILE__SETATTR);
3294 }
3287 3295
3288 /* No one is allowed to remove a SELinux security label. 3296 /* No one is allowed to remove a SELinux security label.
3289 You can change the label, but all data must be labeled. */ 3297 You can change the label, but all data must be labeled. */
@@ -3978,8 +3986,8 @@ static int selinux_task_getioprio(struct task_struct *p)
3978 PROCESS__GETSCHED, NULL); 3986 PROCESS__GETSCHED, NULL);
3979} 3987}
3980 3988
3981int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred, 3989static int selinux_task_prlimit(const struct cred *cred, const struct cred *tcred,
3982 unsigned int flags) 3990 unsigned int flags)
3983{ 3991{
3984 u32 av = 0; 3992 u32 av = 0;
3985 3993
@@ -6252,6 +6260,139 @@ static void selinux_ib_free_security(void *ib_sec)
6252} 6260}
6253#endif 6261#endif
6254 6262
6263#ifdef CONFIG_BPF_SYSCALL
6264static int selinux_bpf(int cmd, union bpf_attr *attr,
6265 unsigned int size)
6266{
6267 u32 sid = current_sid();
6268 int ret;
6269
6270 switch (cmd) {
6271 case BPF_MAP_CREATE:
6272 ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__MAP_CREATE,
6273 NULL);
6274 break;
6275 case BPF_PROG_LOAD:
6276 ret = avc_has_perm(sid, sid, SECCLASS_BPF, BPF__PROG_LOAD,
6277 NULL);
6278 break;
6279 default:
6280 ret = 0;
6281 break;
6282 }
6283
6284 return ret;
6285}
6286
6287static u32 bpf_map_fmode_to_av(fmode_t fmode)
6288{
6289 u32 av = 0;
6290
6291 if (fmode & FMODE_READ)
6292 av |= BPF__MAP_READ;
6293 if (fmode & FMODE_WRITE)
6294 av |= BPF__MAP_WRITE;
6295 return av;
6296}
6297
6298/* This function will check the file pass through unix socket or binder to see
6299 * if it is a bpf related object. And apply correspinding checks on the bpf
6300 * object based on the type. The bpf maps and programs, not like other files and
6301 * socket, are using a shared anonymous inode inside the kernel as their inode.
6302 * So checking that inode cannot identify if the process have privilege to
6303 * access the bpf object and that's why we have to add this additional check in
6304 * selinux_file_receive and selinux_binder_transfer_files.
6305 */
6306static int bpf_fd_pass(struct file *file, u32 sid)
6307{
6308 struct bpf_security_struct *bpfsec;
6309 struct bpf_prog *prog;
6310 struct bpf_map *map;
6311 int ret;
6312
6313 if (file->f_op == &bpf_map_fops) {
6314 map = file->private_data;
6315 bpfsec = map->security;
6316 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6317 bpf_map_fmode_to_av(file->f_mode), NULL);
6318 if (ret)
6319 return ret;
6320 } else if (file->f_op == &bpf_prog_fops) {
6321 prog = file->private_data;
6322 bpfsec = prog->aux->security;
6323 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6324 BPF__PROG_RUN, NULL);
6325 if (ret)
6326 return ret;
6327 }
6328 return 0;
6329}
6330
6331static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6332{
6333 u32 sid = current_sid();
6334 struct bpf_security_struct *bpfsec;
6335
6336 bpfsec = map->security;
6337 return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6338 bpf_map_fmode_to_av(fmode), NULL);
6339}
6340
6341static int selinux_bpf_prog(struct bpf_prog *prog)
6342{
6343 u32 sid = current_sid();
6344 struct bpf_security_struct *bpfsec;
6345
6346 bpfsec = prog->aux->security;
6347 return avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6348 BPF__PROG_RUN, NULL);
6349}
6350
6351static int selinux_bpf_map_alloc(struct bpf_map *map)
6352{
6353 struct bpf_security_struct *bpfsec;
6354
6355 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6356 if (!bpfsec)
6357 return -ENOMEM;
6358
6359 bpfsec->sid = current_sid();
6360 map->security = bpfsec;
6361
6362 return 0;
6363}
6364
6365static void selinux_bpf_map_free(struct bpf_map *map)
6366{
6367 struct bpf_security_struct *bpfsec = map->security;
6368
6369 map->security = NULL;
6370 kfree(bpfsec);
6371}
6372
6373static int selinux_bpf_prog_alloc(struct bpf_prog_aux *aux)
6374{
6375 struct bpf_security_struct *bpfsec;
6376
6377 bpfsec = kzalloc(sizeof(*bpfsec), GFP_KERNEL);
6378 if (!bpfsec)
6379 return -ENOMEM;
6380
6381 bpfsec->sid = current_sid();
6382 aux->security = bpfsec;
6383
6384 return 0;
6385}
6386
6387static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
6388{
6389 struct bpf_security_struct *bpfsec = aux->security;
6390
6391 aux->security = NULL;
6392 kfree(bpfsec);
6393}
6394#endif
6395
6255static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { 6396static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6256 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr), 6397 LSM_HOOK_INIT(binder_set_context_mgr, selinux_binder_set_context_mgr),
6257 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction), 6398 LSM_HOOK_INIT(binder_transaction, selinux_binder_transaction),
@@ -6471,6 +6612,16 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
6471 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match), 6612 LSM_HOOK_INIT(audit_rule_match, selinux_audit_rule_match),
6472 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free), 6613 LSM_HOOK_INIT(audit_rule_free, selinux_audit_rule_free),
6473#endif 6614#endif
6615
6616#ifdef CONFIG_BPF_SYSCALL
6617 LSM_HOOK_INIT(bpf, selinux_bpf),
6618 LSM_HOOK_INIT(bpf_map, selinux_bpf_map),
6619 LSM_HOOK_INIT(bpf_prog, selinux_bpf_prog),
6620 LSM_HOOK_INIT(bpf_map_alloc_security, selinux_bpf_map_alloc),
6621 LSM_HOOK_INIT(bpf_prog_alloc_security, selinux_bpf_prog_alloc),
6622 LSM_HOOK_INIT(bpf_map_free_security, selinux_bpf_map_free),
6623 LSM_HOOK_INIT(bpf_prog_free_security, selinux_bpf_prog_free),
6624#endif
6474}; 6625};
6475 6626
6476static __init int selinux_init(void) 6627static __init int selinux_init(void)