diff options
Diffstat (limited to 'security')
25 files changed, 617 insertions, 270 deletions
diff --git a/security/Kconfig b/security/Kconfig index 5dfc206748c..49b51f96489 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -113,10 +113,12 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR from userspace allocation. Keeping a user from writing to low pages can help reduce the impact of kernel NULL pointer bugs. - For most users with lots of address space a value of 65536 is - reasonable and should cause no problems. Programs which use vm86 - functionality would either need additional permissions from either - the LSM or the capabilities module or have this protection disabled. + For most ia64, ppc64 and x86 users with lots of address space + a value of 65536 is reasonable and should cause no problems. + On arm and other archs it should not be higher than 32768. + Programs which use vm86 functionality would either need additional + permissions from either the LSM or the capabilities module or have + this protection disabled. This value can be changed after boot using the /proc/sys/vm/mmap_min_addr tunable. diff --git a/security/commoncap.c b/security/commoncap.c index 06d5c9469ba..852905789ca 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -267,7 +267,7 @@ static int get_file_caps(struct linux_binprm *bprm) rc = cap_from_disk(&vcaps, bprm, rc); if (rc) printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n", - __FUNCTION__, rc, bprm->filename); + __func__, rc, bprm->filename); out: dput(dentry); @@ -302,7 +302,7 @@ int cap_bprm_set_security (struct linux_binprm *bprm) ret = get_file_caps(bprm); if (ret) printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n", - __FUNCTION__, ret, bprm->filename); + __func__, ret, bprm->filename); /* To support inheritance of root-permissions and suid-root * executables under compatibility mode, we raise all three diff --git a/security/keys/internal.h b/security/keys/internal.h index d36d6939335..7d894ef7037 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -22,16 +22,16 @@ void no_printk(const char *fmt, ...) #ifdef __KDEBUG #define kenter(FMT, ...) \ - printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__) + printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) #define kleave(FMT, ...) \ - printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__) + printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) #define kdebug(FMT, ...) \ printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__) #else #define kenter(FMT, ...) \ - no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__) + no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) #define kleave(FMT, ...) \ - no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__) + no_printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) #define kdebug(FMT, ...) \ no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) #endif diff --git a/security/root_plug.c b/security/root_plug.c index 870f13095bb..6112d1404c8 100644 --- a/security/root_plug.c +++ b/security/root_plug.c @@ -49,7 +49,7 @@ module_param(debug, bool, 0600); do { \ if (debug) \ printk(KERN_DEBUG "%s: %s: " fmt , \ - MY_NAME , __FUNCTION__ , \ + MY_NAME , __func__ , \ ## arg); \ } while (0) diff --git a/security/security.c b/security/security.c index b1387a6b416..9beecac933b 100644 --- a/security/security.c +++ b/security/security.c @@ -57,7 +57,7 @@ int __init security_init(void) if (verify(&dummy_security_ops)) { printk(KERN_ERR "%s could not verify " - "dummy_security_ops structure.\n", __FUNCTION__); + "dummy_security_ops structure.\n", __func__); return -EIO; } @@ -82,7 +82,7 @@ int register_security(struct security_operations *ops) { if (verify(ops)) { printk(KERN_DEBUG "%s could not verify " - "security_operations structure.\n", __FUNCTION__); + "security_operations structure.\n", __func__); return -EINVAL; } @@ -110,13 +110,13 @@ int mod_reg_security(const char *name, struct security_operations *ops) { if (verify(ops)) { printk(KERN_INFO "%s could not verify " - "security operations.\n", __FUNCTION__); + "security operations.\n", __func__); return -EINVAL; } if (ops == security_ops) { printk(KERN_INFO "%s security operations " - "already registered.\n", __FUNCTION__); + "already registered.\n", __func__); return -EINVAL; } diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 2b517d61867..a436d1cfa88 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE int "NSA SELinux maximum supported policy format version value" depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX - range 15 22 + range 15 23 default 19 help This option sets the value for the maximum policy format version diff --git a/security/selinux/Makefile b/security/selinux/Makefile index 00afd85f1ed..d47fc5e545e 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -11,6 +11,7 @@ selinux-y := avc.o \ nlmsgtab.o \ netif.o \ netnode.o \ + netport.o \ exports.o selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 187964e88af..a4fc6e6d038 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -871,6 +871,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, int rc = 0; u32 denied; + BUG_ON(!requested); + rcu_read_lock(); node = avc_lookup(ssid, tsid, tclass, requested); @@ -890,13 +892,14 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, denied = requested & ~(p_ae->avd.allowed); - if (!requested || denied) { - if (selinux_enforcing || (flags & AVC_STRICT)) + if (denied) { + if (flags & AVC_STRICT) rc = -EACCES; + else if (!selinux_enforcing || security_permissive_sid(ssid)) + avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, + tsid, tclass); else - if (node) - avc_update_node(AVC_CALLBACK_GRANT,requested, - ssid,tsid,tclass); + rc = -EACCES; } rcu_read_unlock(); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d39b59cf8a0..34f2d46c798 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -80,6 +80,7 @@ #include "objsec.h" #include "netif.h" #include "netnode.h" +#include "netport.h" #include "xfrm.h" #include "netlabel.h" @@ -161,8 +162,7 @@ static int task_alloc_security(struct task_struct *task) if (!tsec) return -ENOMEM; - tsec->task = task; - tsec->osid = tsec->sid = tsec->ptrace_sid = SECINITSID_UNLABELED; + tsec->osid = tsec->sid = SECINITSID_UNLABELED; task->security = tsec; return 0; @@ -218,7 +218,6 @@ static int file_alloc_security(struct file *file) if (!fsec) return -ENOMEM; - fsec->file = file; fsec->sid = tsec->sid; fsec->fown_sid = tsec->sid; file->f_security = fsec; @@ -275,12 +274,11 @@ static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) if (!ssec) return -ENOMEM; - ssec->sk = sk; ssec->peer_sid = SECINITSID_UNLABELED; ssec->sid = SECINITSID_UNLABELED; sk->sk_security = ssec; - selinux_netlbl_sk_security_init(ssec, family); + selinux_netlbl_sk_security_reset(ssec, family); return 0; } @@ -324,10 +322,10 @@ enum { }; static match_table_t tokens = { - {Opt_context, "context=%s"}, - {Opt_fscontext, "fscontext=%s"}, - {Opt_defcontext, "defcontext=%s"}, - {Opt_rootcontext, "rootcontext=%s"}, + {Opt_context, CONTEXT_STR "%s"}, + {Opt_fscontext, FSCONTEXT_STR "%s"}, + {Opt_defcontext, DEFCONTEXT_STR "%s"}, + {Opt_rootcontext, ROOTCONTEXT_STR "%s"}, {Opt_error, NULL}, }; @@ -671,7 +669,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid); if (rc) { printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", - __FUNCTION__, sb->s_type->name, rc); + __func__, sb->s_type->name, rc); goto out; } @@ -1137,7 +1135,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent } if (!dentry) { printk(KERN_WARNING "%s: no dentry for dev=%s " - "ino=%ld\n", __FUNCTION__, inode->i_sb->s_id, + "ino=%ld\n", __func__, inode->i_sb->s_id, inode->i_ino); goto out_unlock; } @@ -1175,7 +1173,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (rc < 0) { if (rc != -ENODATA) { printk(KERN_WARNING "%s: getxattr returned " - "%d for dev=%s ino=%ld\n", __FUNCTION__, + "%d for dev=%s ino=%ld\n", __func__, -rc, inode->i_sb->s_id, inode->i_ino); kfree(context); goto out_unlock; @@ -1190,7 +1188,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (rc) { printk(KERN_WARNING "%s: context_to_sid(%s) " "returned %d for dev=%s ino=%ld\n", - __FUNCTION__, context, -rc, + __func__, context, -rc, inode->i_sb->s_id, inode->i_ino); kfree(context); /* Leave with the unlabeled SID */ @@ -1618,6 +1616,35 @@ static inline u32 file_mask_to_av(int mode, int mask) return av; } +/* + * Convert a file mask to an access vector and include the correct open + * open permission. + */ +static inline u32 open_file_mask_to_av(int mode, int mask) +{ + u32 av = file_mask_to_av(mode, mask); + + if (selinux_policycap_openperm) { + /* + * lnk files and socks do not really have an 'open' + */ + if (S_ISREG(mode)) + av |= FILE__OPEN; + else if (S_ISCHR(mode)) + av |= CHR_FILE__OPEN; + else if (S_ISBLK(mode)) + av |= BLK_FILE__OPEN; + else if (S_ISFIFO(mode)) + av |= FIFO_FILE__OPEN; + else if (S_ISDIR(mode)) + av |= DIR__OPEN; + else + printk(KERN_ERR "SELinux: WARNING: inside open_file_to_av " + "with unknown mode:%x\n", mode); + } + return av; +} + /* Convert a Linux file to an access vector. */ static inline u32 file_to_av(struct file *file) { @@ -1645,19 +1672,13 @@ static inline u32 file_to_av(struct file *file) static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) { - struct task_security_struct *psec = parent->security; - struct task_security_struct *csec = child->security; int rc; rc = secondary_ops->ptrace(parent,child); if (rc) return rc; - rc = task_has_perm(parent, child, PROCESS__PTRACE); - /* Save the SID of the tracing process for later use in apply_creds. */ - if (!(child->ptrace & PT_PTRACED) && !rc) - csec->ptrace_sid = psec->sid; - return rc; + return task_has_perm(parent, child, PROCESS__PTRACE); } static int selinux_capget(struct task_struct *target, kernel_cap_t *effective, @@ -1879,6 +1900,22 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) return __vm_enough_memory(mm, pages, cap_sys_admin); } +/** + * task_tracer_task - return the task that is tracing the given task + * @task: task to consider + * + * Returns NULL if noone is tracing @task, or the &struct task_struct + * pointer to its tracer. + * + * Must be called under rcu_read_lock(). + */ +static struct task_struct *task_tracer_task(struct task_struct *task) +{ + if (task->ptrace & PT_PTRACED) + return rcu_dereference(task->parent); + return NULL; +} + /* binprm security operations */ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) @@ -1889,7 +1926,6 @@ static int selinux_bprm_alloc_security(struct linux_binprm *bprm) if (!bsec) return -ENOMEM; - bsec->bprm = bprm; bsec->sid = SECINITSID_UNLABELED; bsec->set = 0; @@ -2126,12 +2162,25 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and kill. */ if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { - rc = avc_has_perm(tsec->ptrace_sid, sid, - SECCLASS_PROCESS, PROCESS__PTRACE, - NULL); - if (rc) { - bsec->unsafe = 1; - return; + struct task_struct *tracer; + struct task_security_struct *sec; + u32 ptsid = 0; + + rcu_read_lock(); + tracer = task_tracer_task(current); + if (likely(tracer != NULL)) { + sec = tracer->security; + ptsid = sec->sid; + } + rcu_read_unlock(); + + if (ptsid != 0) { + rc = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, + PROCESS__PTRACE, NULL); + if (rc) { + bsec->unsafe = 1; + return; + } } } tsec->sid = sid; @@ -2239,10 +2288,10 @@ static inline int match_prefix(char *prefix, int plen, char *option, int olen) static inline int selinux_option(char *option, int len) { - return (match_prefix("context=", sizeof("context=")-1, option, len) || - match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) || - match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) || - match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len)); + return (match_prefix(CONTEXT_STR, sizeof(CONTEXT_STR)-1, option, len) || + match_prefix(FSCONTEXT_STR, sizeof(FSCONTEXT_STR)-1, option, len) || + match_prefix(DEFCONTEXT_STR, sizeof(DEFCONTEXT_STR)-1, option, len) || + match_prefix(ROOTCONTEXT_STR, sizeof(ROOTCONTEXT_STR)-1, option, len)); } static inline void take_option(char **to, char *from, int *first, int len) @@ -2412,7 +2461,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, printk(KERN_WARNING "%s: " "security_transition_sid failed, rc=%d (dev=%s " "ino=%ld)\n", - __FUNCTION__, + __func__, -rc, inode->i_sb->s_id, inode->i_ino); return rc; } @@ -2536,7 +2585,7 @@ static int selinux_inode_permission(struct inode *inode, int mask, } return inode_has_perm(current, inode, - file_mask_to_av(inode->i_mode, mask), NULL); + open_file_mask_to_av(inode->i_mode, mask), NULL); } static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) @@ -2646,7 +2695,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name, rc = security_context_to_sid(value, size, &newsid); if (rc) { printk(KERN_WARNING "%s: unable to obtain SID for context " - "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc); + "%s, rc=%d\n", __func__, (char *)value, -rc); return; } @@ -3087,11 +3136,6 @@ static int selinux_task_alloc_security(struct task_struct *tsk) tsec2->keycreate_sid = tsec1->keycreate_sid; tsec2->sockcreate_sid = tsec1->sockcreate_sid; - /* Retain ptracer SID across fork, if any. - This will be reset by the ptrace hook upon any - subsequent ptrace_attach operations. */ - tsec2->ptrace_sid = tsec1->ptrace_sid; - return 0; } @@ -3627,10 +3671,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in inet_get_local_port_range(&low, &high); if (snum < max(PROT_SOCK, low) || snum > high) { - err = security_port_sid(sk->sk_family, - sk->sk_type, - sk->sk_protocol, snum, - &sid); + err = sel_netport_sid(sk->sk_protocol, + snum, &sid); if (err) goto out; AVC_AUDIT_DATA_INIT(&ad,NET); @@ -3718,8 +3760,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, snum = ntohs(addr6->sin6_port); } - err = security_port_sid(sk->sk_family, sk->sk_type, - sk->sk_protocol, snum, &sid); + err = sel_netport_sid(sk->sk_protocol, snum, &sid); if (err) goto out; @@ -3950,9 +3991,8 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk, if (!recv_perm) return 0; - err = security_port_sid(sk->sk_family, sk->sk_type, - sk->sk_protocol, ntohs(ad->u.net.sport), - &port_sid); + err = sel_netport_sid(sk->sk_protocol, + ntohs(ad->u.net.sport), &port_sid); if (unlikely(err)) { printk(KERN_WARNING "SELinux: failure in" @@ -4139,7 +4179,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) newssec->peer_sid = ssec->peer_sid; newssec->sclass = ssec->sclass; - selinux_netlbl_sk_security_clone(ssec, newssec); + selinux_netlbl_sk_security_reset(newssec, newsk->sk_family); } static void selinux_sk_getsecid(struct sock *sk, u32 *secid) @@ -4373,9 +4413,8 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk, if (send_perm != 0) return 0; - err = security_port_sid(sk->sk_family, sk->sk_type, - sk->sk_protocol, ntohs(ad->u.net.dport), - &port_sid); + err = sel_netport_sid(sk->sk_protocol, + ntohs(ad->u.net.dport), &port_sid); if (unlikely(err)) { printk(KERN_WARNING "SELinux: failure in" @@ -4561,7 +4600,6 @@ static int ipc_alloc_security(struct task_struct *task, return -ENOMEM; isec->sclass = sclass; - isec->ipc_perm = perm; isec->sid = tsec->sid; perm->security = isec; @@ -4583,7 +4621,6 @@ static int msg_msg_alloc_security(struct msg_msg *msg) if (!msec) return -ENOMEM; - msec->msg = msg; msec->sid = SECINITSID_UNLABELED; msg->security = msec; @@ -4994,14 +5031,14 @@ static int selinux_register_security (const char *name, struct security_operatio { if (secondary_ops != original_ops) { printk(KERN_ERR "%s: There is already a secondary security " - "module registered.\n", __FUNCTION__); + "module registered.\n", __func__); return -EINVAL; } secondary_ops = ops; printk(KERN_INFO "%s: Registering secondary module %s\n", - __FUNCTION__, + __func__, name); return 0; @@ -5057,6 +5094,7 @@ static int selinux_setprocattr(struct task_struct *p, char *name, void *value, size_t size) { struct task_security_struct *tsec; + struct task_struct *tracer; u32 sid = 0; int error; char *str = value; @@ -5145,18 +5183,24 @@ static int selinux_setprocattr(struct task_struct *p, /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and fail. */ task_lock(p); - if (p->ptrace & PT_PTRACED) { - error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, + rcu_read_lock(); + tracer = task_tracer_task(p); + if (tracer != NULL) { + struct task_security_struct *ptsec = tracer->security; + u32 ptsid = ptsec->sid; + rcu_read_unlock(); + error = avc_has_perm_noaudit(ptsid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, 0, &avd); if (!error) tsec->sid = sid; task_unlock(p); - avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, + avc_audit(ptsid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, &avd, error, NULL); if (error) return error; } else { + rcu_read_unlock(); tsec->sid = sid; task_unlock(p); } @@ -5194,7 +5238,6 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk, if (!ksec) return -ENOMEM; - ksec->obj = k; if (tsec->keycreate_sid) ksec->sid = tsec->keycreate_sid; else @@ -5631,5 +5674,3 @@ int selinux_disable(void) return 0; } #endif - - diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index d5696690d3a..1223b4ff9be 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h @@ -14,12 +14,17 @@ S_(SECCLASS_DIR, DIR__REPARENT, "reparent") S_(SECCLASS_DIR, DIR__SEARCH, "search") S_(SECCLASS_DIR, DIR__RMDIR, "rmdir") + S_(SECCLASS_DIR, DIR__OPEN, "open") S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans") S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") + S_(SECCLASS_FILE, FILE__OPEN, "open") S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint") S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") + S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open") + S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open") + S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open") S_(SECCLASS_FD, FD__USE, "use") S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 75b41311ab8..c4c51165c50 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h @@ -79,6 +79,7 @@ #define DIR__REPARENT 0x00080000UL #define DIR__SEARCH 0x00100000UL #define DIR__RMDIR 0x00200000UL +#define DIR__OPEN 0x00400000UL #define FILE__IOCTL 0x00000001UL #define FILE__READ 0x00000002UL #define FILE__WRITE 0x00000004UL @@ -99,6 +100,7 @@ #define FILE__EXECUTE_NO_TRANS 0x00020000UL #define FILE__ENTRYPOINT 0x00040000UL #define FILE__EXECMOD 0x00080000UL +#define FILE__OPEN 0x00100000UL #define LNK_FILE__IOCTL 0x00000001UL #define LNK_FILE__READ 0x00000002UL #define LNK_FILE__WRITE 0x00000004UL @@ -136,6 +138,7 @@ #define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL #define CHR_FILE__ENTRYPOINT 0x00040000UL #define CHR_FILE__EXECMOD 0x00080000UL +#define CHR_FILE__OPEN 0x00100000UL #define BLK_FILE__IOCTL 0x00000001UL #define BLK_FILE__READ 0x00000002UL #define BLK_FILE__WRITE 0x00000004UL @@ -153,6 +156,7 @@ #define BLK_FILE__SWAPON 0x00004000UL #define BLK_FILE__QUOTAON 0x00008000UL #define BLK_FILE__MOUNTON 0x00010000UL +#define BLK_FILE__OPEN 0x00020000UL #define SOCK_FILE__IOCTL 0x00000001UL #define SOCK_FILE__READ 0x00000002UL #define SOCK_FILE__WRITE 0x00000004UL @@ -187,6 +191,7 @@ #define FIFO_FILE__SWAPON 0x00004000UL #define FIFO_FILE__QUOTAON 0x00008000UL #define FIFO_FILE__MOUNTON 0x00010000UL +#define FIFO_FILE__OPEN 0x00020000UL #define FD__USE 0x00000001UL #define SOCKET__IOCTL 0x00000001UL #define SOCKET__READ 0x00000002UL diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h index 00a2809c850..9a9e7cd9a37 100644 --- a/security/selinux/include/netlabel.h +++ b/security/selinux/include/netlabel.h @@ -41,10 +41,6 @@ void selinux_netlbl_cache_invalidate(void); void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, int family); -void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, - int family); -void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, - struct sk_security_struct *newssec); int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, @@ -73,18 +69,6 @@ static inline void selinux_netlbl_sk_security_reset( { return; } -static inline void selinux_netlbl_sk_security_init( - struct sk_security_struct *ssec, - int family) -{ - return; -} -static inline void selinux_netlbl_sk_security_clone( - struct sk_security_struct *ssec, - struct sk_security_struct *newssec) -{ - return; -} static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u16 family, diff --git a/security/selinux/include/netport.h b/security/selinux/include/netport.h new file mode 100644 index 00000000000..8991752eaf9 --- /dev/null +++ b/security/selinux/include/netport.h @@ -0,0 +1,31 @@ +/* + * Network port table + * + * SELinux must keep a mapping of network ports to labels/SIDs. This + * mapping is maintained as part of the normal policy but a fast cache is + * needed to reduce the lookup overhead. + * + * Author: Paul Moore <paul.moore@hp.com> + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2008 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _SELINUX_NETPORT_H +#define _SELINUX_NETPORT_H + +int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid); + +#endif diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index c6c2bb4ebac..300b61bad7b 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -28,14 +28,12 @@ #include "avc.h" struct task_security_struct { - struct task_struct *task; /* back pointer to task object */ u32 osid; /* SID prior to last execve */ u32 sid; /* current SID */ u32 exec_sid; /* exec SID */ u32 create_sid; /* fscreate SID */ u32 keycreate_sid; /* keycreate SID */ u32 sockcreate_sid; /* fscreate SID */ - u32 ptrace_sid; /* SID of ptrace parent */ }; struct inode_security_struct { @@ -50,7 +48,6 @@ struct inode_security_struct { }; struct file_security_struct { - struct file *file; /* back pointer to file object */ u32 sid; /* SID of open file description */ u32 fown_sid; /* SID of file owner (for SIGIO) */ u32 isid; /* SID of inode at the time of file open */ @@ -73,18 +70,15 @@ struct superblock_security_struct { }; struct msg_security_struct { - struct msg_msg *msg; /* back pointer */ u32 sid; /* SID of message */ }; struct ipc_security_struct { - struct kern_ipc_perm *ipc_perm; /* back pointer */ u16 sclass; /* security class of this object */ u32 sid; /* SID of IPC resource */ }; struct bprm_security_struct { - struct linux_binprm *bprm; /* back pointer to bprm object */ u32 sid; /* SID for transformed process */ unsigned char set; @@ -109,8 +103,13 @@ struct netnode_security_struct { u16 family; /* address family */ }; +struct netport_security_struct { + u32 sid; /* SID for this node */ + u16 port; /* port number */ + u8 protocol; /* transport protocol */ +}; + struct sk_security_struct { - struct sock *sk; /* back pointer to sk object */ u32 sid; /* SID of this object */ u32 peer_sid; /* SID of peer */ u16 sclass; /* sock security class */ @@ -120,12 +119,10 @@ struct sk_security_struct { NLBL_REQUIRE, NLBL_LABELED, } nlbl_state; - spinlock_t nlbl_lock; /* protects nlbl_state */ #endif }; struct key_security_struct { - struct key *obj; /* back pointer */ u32 sid; /* SID of key */ }; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 44e12ec8809..1904c462a60 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -26,13 +26,14 @@ #define POLICYDB_VERSION_AVTAB 20 #define POLICYDB_VERSION_RANGETRANS 21 #define POLICYDB_VERSION_POLCAP 22 +#define POLICYDB_VERSION_PERMISSIVE 23 /* Range of policy versions we understand*/ #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE #else -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE #endif #define CONTEXT_MNT 0x01 @@ -40,6 +41,11 @@ #define ROOTCONTEXT_MNT 0x04 #define DEFCONTEXT_MNT 0x08 +#define CONTEXT_STR "context=" +#define FSCONTEXT_STR "fscontext=" +#define ROOTCONTEXT_STR "rootcontext=" +#define DEFCONTEXT_STR "defcontext=" + struct netlbl_lsm_secattr; extern int selinux_enabled; @@ -48,11 +54,13 @@ extern int selinux_mls_enabled; /* Policy capabilities */ enum { POLICYDB_CAPABILITY_NETPEER, + POLICYDB_CAPABILITY_OPENPERM, __POLICYDB_CAPABILITY_MAX }; #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1) extern int selinux_policycap_netpeer; +extern int selinux_policycap_openperm; int security_load_policy(void * data, size_t len); @@ -67,6 +75,8 @@ struct av_decision { u32 seqno; }; +int security_permissive_sid(u32 sid); + int security_compute_av(u32 ssid, u32 tsid, u16 tclass, u32 requested, struct av_decision *avd); @@ -92,8 +102,7 @@ int security_context_to_sid_default(char *scontext, u32 scontext_len, int security_get_user_sids(u32 callsid, char *username, u32 **sids, u32 *nel); -int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port, - u32 *out_sid); +int security_port_sid(u8 protocol, u16 port, u32 *out_sid); int security_netif_sid(char *name, u32 *if_sid); diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 0fa2be4149e..e8ee91ac12e 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -34,6 +34,7 @@ #include "objsec.h" #include "security.h" +#include "netlabel.h" /** * selinux_netlbl_sidlookup_cached - Cache a SID lookup @@ -69,9 +70,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb, * * Description: * Attempt to label a socket using the NetLabel mechanism using the given - * SID. Returns zero values on success, negative values on failure. The - * caller is responsibile for calling rcu_read_lock() before calling this - * this function and rcu_read_unlock() after this function returns. + * SID. Returns zero values on success, negative values on failure. * */ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) @@ -86,11 +85,8 @@ static int selinux_netlbl_sock_setsid(struct sock *sk, u32 sid) if (rc != 0) goto sock_setsid_return; rc = netlbl_sock_setattr(sk, &secattr); - if (rc == 0) { - spin_lock_bh(&sksec->nlbl_lock); + if (rc == 0) sksec->nlbl_state = NLBL_LABELED; - spin_unlock_bh(&sksec->nlbl_lock); - } sock_setsid_return: netlbl_secattr_destroy(&secattr); @@ -129,45 +125,6 @@ void selinux_netlbl_sk_security_reset(struct sk_security_struct *ssec, } /** - * selinux_netlbl_sk_security_init - Setup the NetLabel fields - * @ssec: the sk_security_struct - * @family: the socket family - * - * Description: - * Called when a new sk_security_struct is allocated to initialize the NetLabel - * fields. - * - */ -void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, - int family) -{ - /* No locking needed, we are the only one who has access to ssec */ - selinux_netlbl_sk_security_reset(ssec, family); - spin_lock_init(&ssec->nlbl_lock); -} - -/** - * selinux_netlbl_sk_security_clone - Copy the NetLabel fields - * @ssec: the original sk_security_struct - * @newssec: the cloned sk_security_struct - * - * Description: - * Clone the NetLabel specific sk_security_struct fields from @ssec to - * @newssec. - * - */ -void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, - struct sk_security_struct *newssec) -{ - /* We don't need to take newssec->nlbl_lock because we are the only - * thread with access to newssec, but we do need to take the RCU read - * lock as other threads could have access to ssec */ - rcu_read_lock(); - selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family); - rcu_read_unlock(); -} - -/** * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel * @skb: the packet * @family: protocol family @@ -221,12 +178,8 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) struct netlbl_lsm_secattr secattr; u32 nlbl_peer_sid; - rcu_read_lock(); - - if (sksec->nlbl_state != NLBL_REQUIRE) { - rcu_read_unlock(); + if (sksec->nlbl_state != NLBL_REQUIRE) return; - } netlbl_secattr_init(&secattr); if (netlbl_sock_getattr(sk, &secattr) == 0 && @@ -239,8 +192,6 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) * here we will pick up the pieces in later calls to * selinux_netlbl_inode_permission(). */ selinux_netlbl_sock_setsid(sk, sksec->sid); - - rcu_read_unlock(); } /** @@ -254,16 +205,13 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) */ int selinux_netlbl_socket_post_create(struct socket *sock) { - int rc = 0; struct sock *sk = sock->sk; struct sk_security_struct *sksec = sk->sk_security; - rcu_read_lock(); - if (sksec->nlbl_state == NLBL_REQUIRE) - rc = selinux_netlbl_sock_setsid(sk, sksec->sid); - rcu_read_unlock(); + if (sksec->nlbl_state != NLBL_REQUIRE) + return 0; - return rc; + return selinux_netlbl_sock_setsid(sk, sksec->sid); } /** @@ -288,21 +236,21 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) if (!S_ISSOCK(inode->i_mode) || ((mask & (MAY_WRITE | MAY_APPEND)) == 0)) return 0; + sock = SOCKET_I(inode); sk = sock->sk; sksec = sk->sk_security; - - rcu_read_lock(); - if (sksec->nlbl_state != NLBL_REQUIRE) { - rcu_read_unlock(); + if (sksec->nlbl_state != NLBL_REQUIRE) return 0; - } + local_bh_disable(); bh_lock_sock_nested(sk); - rc = selinux_netlbl_sock_setsid(sk, sksec->sid); + if (likely(sksec->nlbl_state == NLBL_REQUIRE)) + rc = selinux_netlbl_sock_setsid(sk, sksec->sid); + else + rc = 0; bh_unlock_sock(sk); local_bh_enable(); - rcu_read_unlock(); return rc; } @@ -385,7 +333,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr secattr; - rcu_read_lock(); if (level == IPPROTO_IP && optname == IP_OPTIONS && sksec->nlbl_state == NLBL_LABELED) { netlbl_secattr_init(&secattr); @@ -396,7 +343,6 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock, rc = -EACCES; netlbl_secattr_destroy(&secattr); } - rcu_read_unlock(); return rc; } diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index b59871d74da..6214a7a7314 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c @@ -89,7 +89,7 @@ out: nlmsg_failure: kfree_skb(skb); oom: - printk(KERN_ERR "SELinux: OOM in %s\n", __FUNCTION__); + printk(KERN_ERR "SELinux: OOM in %s\n", __func__); goto out; } diff --git a/security/selinux/netport.c b/security/selinux/netport.c new file mode 100644 index 00000000000..68ede3c498a --- /dev/null +++ b/security/selinux/netport.c @@ -0,0 +1,286 @@ +/* + * Network port table + * + * SELinux must keep a mapping of network ports to labels/SIDs. This + * mapping is maintained as part of the normal policy but a fast cache is + * needed to reduce the lookup overhead. + * + * Author: Paul Moore <paul.moore@hp.com> + * + * This code is heavily based on the "netif" concept originally developed by + * James Morris <jmorris@redhat.com> + * (see security/selinux/netif.c for more information) + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2008 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/types.h> +#include <linux/rcupdate.h> +#include <linux/list.h> +#include <linux/spinlock.h> +#include <linux/in.h> +#include <linux/in6.h> +#include <linux/ip.h> +#include <linux/ipv6.h> +#include <net/ip.h> +#include <net/ipv6.h> +#include <asm/bug.h> + +#include "netport.h" +#include "objsec.h" + +#define SEL_NETPORT_HASH_SIZE 256 +#define SEL_NETPORT_HASH_BKT_LIMIT 16 + +struct sel_netport_bkt { + int size; + struct list_head list; +}; + +struct sel_netport { + struct netport_security_struct psec; + + struct list_head list; + struct rcu_head rcu; +}; + +/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason + * for this is that I suspect most users will not make heavy use of both + * address families at the same time so one table will usually end up wasted, + * if this becomes a problem we can always add a hash table for each address + * family later */ + +static LIST_HEAD(sel_netport_list); +static DEFINE_SPINLOCK(sel_netport_lock); +static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE]; + +/** + * sel_netport_free - Frees a port entry + * @p: the entry's RCU field + * + * Description: + * This function is designed to be used as a callback to the call_rcu() + * function so that memory allocated to a hash table port entry can be + * released safely. + * + */ +static void sel_netport_free(struct rcu_head *p) +{ + struct sel_netport *port = container_of(p, struct sel_netport, rcu); + kfree(port); +} + +/** + * sel_netport_hashfn - Hashing function for the port table + * @pnum: port number + * + * Description: + * This is the hashing function for the port table, it returns the bucket + * number for the given port. + * + */ +static unsigned int sel_netport_hashfn(u16 pnum) +{ + return (pnum & (SEL_NETPORT_HASH_SIZE - 1)); +} + +/** + * sel_netport_find - Search for a port record + * @protocol: protocol + * @port: pnum + * + * Description: + * Search the network port table and return the matching record. If an entry + * can not be found in the table return NULL. + * + */ +static struct sel_netport *sel_netport_find(u8 protocol, u16 pnum) +{ + unsigned int idx; + struct sel_netport *port; + + idx = sel_netport_hashfn(pnum); + list_for_each_entry_rcu(port, &sel_netport_hash[idx].list, list) + if (port->psec.port == pnum && + port->psec.protocol == protocol) + return port; + + return NULL; +} + +/** + * sel_netport_insert - Insert a new port into the table + * @port: the new port record + * + * Description: + * Add a new port record to the network address hash table. Returns zero on + * success, negative values on failure. + * + */ +static int sel_netport_insert(struct sel_netport *port) +{ + unsigned int idx; + + /* we need to impose a limit on the growth of the hash table so check + * this bucket to make sure it is within the specified bounds */ + idx = sel_netport_hashfn(port->psec.port); + list_add_rcu(&port->list, &sel_netport_hash[idx].list); + if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) { + struct sel_netport *tail; + tail = list_entry(port->list.prev, struct sel_netport, list); + list_del_rcu(port->list.prev); + call_rcu(&tail->rcu, sel_netport_free); + } else + sel_netport_hash[idx].size++; + + return 0; +} + +/** + * sel_netport_sid_slow - Lookup the SID of a network address using the policy + * @protocol: protocol + * @pnum: port + * @sid: port SID + * + * Description: + * This function determines the SID of a network port by quering the security + * policy. The result is added to the network port table to speedup future + * queries. Returns zero on success, negative values on failure. + * + */ +static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid) +{ + int ret; + struct sel_netport *port; + struct sel_netport *new = NULL; + + spin_lock_bh(&sel_netport_lock); + port = sel_netport_find(protocol, pnum); + if (port != NULL) { + *sid = port->psec.sid; + ret = 0; + goto out; + } + new = kzalloc(sizeof(*new), GFP_ATOMIC); + if (new == NULL) { + ret = -ENOMEM; + goto out; + } + ret = security_port_sid(protocol, pnum, &new->psec.sid); + if (ret != 0) + goto out; + new->psec.port = pnum; + new->psec.protocol = protocol; + ret = sel_netport_insert(new); + if (ret != 0) + goto out; + *sid = new->psec.sid; + +out: + spin_unlock_bh(&sel_netport_lock); + if (unlikely(ret)) { + printk(KERN_WARNING + "SELinux: failure in sel_netport_sid_slow()," + " unable to determine network port label\n"); + kfree(new); + } + return ret; +} + +/** + * sel_netport_sid - Lookup the SID of a network port + * @protocol: protocol + * @pnum: port + * @sid: port SID + * + * Description: + * This function determines the SID of a network port using the fastest method + * possible. First the port table is queried, but if an entry can't be found + * then the policy is queried and the result is added to the table to speedup + * future queries. Returns zero on success, negative values on failure. + * + */ +int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid) +{ + struct sel_netport *port; + + rcu_read_lock(); + port = sel_netport_find(protocol, pnum); + if (port != NULL) { + *sid = port->psec.sid; + rcu_read_unlock(); + return 0; + } + rcu_read_unlock(); + + return sel_netport_sid_slow(protocol, pnum, sid); +} + +/** + * sel_netport_flush - Flush the entire network port table + * + * Description: + * Remove all entries from the network address table. + * + */ +static void sel_netport_flush(void) +{ + unsigned int idx; + struct sel_netport *port; + + spin_lock_bh(&sel_netport_lock); + for (idx = 0; idx < SEL_NETPORT_HASH_SIZE; idx++) { + list_for_each_entry(port, &sel_netport_hash[idx].list, list) { + list_del_rcu(&port->list); + call_rcu(&port->rcu, sel_netport_free); + } + sel_netport_hash[idx].size = 0; + } + spin_unlock_bh(&sel_netport_lock); +} + +static int sel_netport_avc_callback(u32 event, u32 ssid, u32 tsid, + u16 class, u32 perms, u32 *retained) +{ + if (event == AVC_CALLBACK_RESET) { + sel_netport_flush(); + synchronize_net(); + } + return 0; +} + +static __init int sel_netport_init(void) +{ + int iter; + int ret; + + if (!selinux_enabled) + return 0; + + for (iter = 0; iter < SEL_NETPORT_HASH_SIZE; iter++) { + INIT_LIST_HEAD(&sel_netport_hash[iter].list); + sel_netport_hash[iter].size = 0; + } + + ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET, + SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0); + if (ret != 0) + panic("avc_add_callback() failed, error %d\n", ret); + + return ret; +} + +__initcall(sel_netport_init); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 0341567665b..26fabad0976 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -42,7 +42,8 @@ /* Policy capability filenames */ static char *policycap_names[] = { - "network_peer_controls" + "network_peer_controls", + "open_perms" }; unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; @@ -391,7 +392,7 @@ static ssize_t sel_write_context(struct file * file, char *buf, size_t size) if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "%s: context size (%u) exceeds payload " - "max\n", __FUNCTION__, len); + "max\n", __func__, len); length = -ERANGE; goto out; } @@ -644,7 +645,7 @@ static ssize_t sel_write_create(struct file * file, char *buf, size_t size) if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "%s: context size (%u) exceeds payload " - "max\n", __FUNCTION__, len); + "max\n", __func__, len); length = -ERANGE; goto out3; } @@ -821,7 +822,7 @@ static ssize_t sel_write_member(struct file * file, char *buf, size_t size) if (len > SIMPLE_TRANSACTION_LIMIT) { printk(KERN_ERR "%s: context size (%u) exceeds payload " - "max\n", __FUNCTION__, len); + "max\n", __func__, len); length = -ERANGE; goto out3; } @@ -1760,7 +1761,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent) out: return ret; err: - printk(KERN_ERR "%s: failed while creating inodes\n", __FUNCTION__); + printk(KERN_ERR "%s: failed while creating inodes\n", __func__); goto out; } diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index cd10e27fc9e..916e73a18bc 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -280,8 +280,8 @@ int avtab_alloc(struct avtab *h, u32 nrules) h->nel = 0; h->nslot = nslot; h->mask = mask; - printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. " - "Num of rules:%d\n", h->nslot, nrules); + printk(KERN_DEBUG "SELinux: %d avtab hash slots, %d rules.\n", + h->nslot, nrules); return 0; } @@ -345,18 +345,18 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, if (vers < POLICYDB_VERSION_AVTAB) { rc = next_entry(buf32, fp, sizeof(u32)); if (rc < 0) { - printk(KERN_ERR "security: avtab: truncated entry\n"); + printk(KERN_ERR "SELinux: avtab: truncated entry\n"); return -1; } items2 = le32_to_cpu(buf32[0]); if (items2 > ARRAY_SIZE(buf32)) { - printk(KERN_ERR "security: avtab: entry overflow\n"); + printk(KERN_ERR "SELinux: avtab: entry overflow\n"); return -1; } rc = next_entry(buf32, fp, sizeof(u32)*items2); if (rc < 0) { - printk(KERN_ERR "security: avtab: truncated entry\n"); + printk(KERN_ERR "SELinux: avtab: truncated entry\n"); return -1; } items = 0; @@ -364,19 +364,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, val = le32_to_cpu(buf32[items++]); key.source_type = (u16)val; if (key.source_type != val) { - printk("security: avtab: truncated source type\n"); + printk("SELinux: avtab: truncated source type\n"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_type = (u16)val; if (key.target_type != val) { - printk("security: avtab: truncated target type\n"); + printk("SELinux: avtab: truncated target type\n"); return -1; } val = le32_to_cpu(buf32[items++]); key.target_class = (u16)val; if (key.target_class != val) { - printk("security: avtab: truncated target class\n"); + printk("SELinux: avtab: truncated target class\n"); return -1; } @@ -384,12 +384,12 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; if (!(val & (AVTAB_AV | AVTAB_TYPE))) { - printk("security: avtab: null entry\n"); + printk("SELinux: avtab: null entry\n"); return -1; } if ((val & AVTAB_AV) && (val & AVTAB_TYPE)) { - printk("security: avtab: entry has both access vectors and types\n"); + printk("SELinux: avtab: entry has both access vectors and types\n"); return -1; } @@ -403,7 +403,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, } if (items != items2) { - printk("security: avtab: entry only had %d items, expected %d\n", items2, items); + printk("SELinux: avtab: entry only had %d items, expected %d\n", items2, items); return -1; } return 0; @@ -411,7 +411,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, rc = next_entry(buf16, fp, sizeof(u16)*4); if (rc < 0) { - printk("security: avtab: truncated entry\n"); + printk("SELinux: avtab: truncated entry\n"); return -1; } @@ -424,7 +424,7 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, if (!policydb_type_isvalid(pol, key.source_type) || !policydb_type_isvalid(pol, key.target_type) || !policydb_class_isvalid(pol, key.target_class)) { - printk(KERN_WARNING "security: avtab: invalid type or class\n"); + printk(KERN_WARNING "SELinux: avtab: invalid type or class\n"); return -1; } @@ -435,19 +435,19 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol, } if (!set || set > 1) { printk(KERN_WARNING - "security: avtab: more than one specifier\n"); + "SELinux: avtab: more than one specifier\n"); return -1; } rc = next_entry(buf32, fp, sizeof(u32)); if (rc < 0) { - printk("security: avtab: truncated entry\n"); + printk("SELinux: avtab: truncated entry\n"); return -1; } datum.data = le32_to_cpu(*buf32); if ((key.specified & AVTAB_TYPE) && !policydb_type_isvalid(pol, datum.data)) { - printk(KERN_WARNING "security: avtab: invalid type\n"); + printk(KERN_WARNING "SELinux: avtab: invalid type\n"); return -1; } return insertf(a, &key, &datum, p); @@ -468,12 +468,12 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) { - printk(KERN_ERR "security: avtab: truncated table\n"); + printk(KERN_ERR "SELinux: avtab: truncated table\n"); goto bad; } nel = le32_to_cpu(buf[0]); if (!nel) { - printk(KERN_ERR "security: avtab: table is empty\n"); + printk(KERN_ERR "SELinux: avtab: table is empty\n"); rc = -EINVAL; goto bad; } @@ -486,9 +486,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol) rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL); if (rc) { if (rc == -ENOMEM) - printk(KERN_ERR "security: avtab: out of memory\n"); + printk(KERN_ERR "SELinux: avtab: out of memory\n"); else if (rc == -EEXIST) - printk(KERN_ERR "security: avtab: duplicate entry\n"); + printk(KERN_ERR "SELinux: avtab: duplicate entry\n"); else rc = -EINVAL; goto bad; diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 50ad85d4b77..a996cf1d378 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -96,7 +96,7 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node) if (new_state != node->cur_state) { node->cur_state = new_state; if (new_state == -1) - printk(KERN_ERR "security: expression result was undefined - disabling all rules.\n"); + printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); /* turn the rules on or off */ for (cur = node->true_list; cur != NULL; cur = cur->next) { if (new_state <= 0) { @@ -276,7 +276,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum */ if (k->specified & AVTAB_TYPE) { if (avtab_search(&p->te_avtab, k)) { - printk("security: type rule already exists outside of a conditional."); + printk("SELinux: type rule already exists outside of a conditional."); goto err; } /* @@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum node_ptr = avtab_search_node(&p->te_cond_avtab, k); if (node_ptr) { if (avtab_search_node_next(node_ptr, k->specified)) { - printk("security: too many conflicting type rules."); + printk("SELinux: too many conflicting type rules."); goto err; } found = 0; @@ -302,13 +302,13 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum } } if (!found) { - printk("security: conflicting type rules.\n"); + printk("SELinux: conflicting type rules.\n"); goto err; } } } else { if (avtab_search(&p->te_cond_avtab, k)) { - printk("security: conflicting type rules when adding type rule for true.\n"); + printk("SELinux: conflicting type rules when adding type rule for true.\n"); goto err; } } @@ -316,7 +316,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); if (!node_ptr) { - printk("security: could not insert rule."); + printk("SELinux: could not insert rule."); goto err; } @@ -376,12 +376,12 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * static int expr_isvalid(struct policydb *p, struct cond_expr *expr) { if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { - printk("security: conditional expressions uses unknown operator.\n"); + printk("SELinux: conditional expressions uses unknown operator.\n"); return 0; } if (expr->bool > p->p_bools.nprim) { - printk("security: conditional expressions uses unknown bool.\n"); + printk("SELinux: conditional expressions uses unknown bool.\n"); return 0; } return 1; diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 920b5e36a1a..e499af474b3 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c @@ -364,7 +364,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) count = le32_to_cpu(buf[2]); if (mapunit != sizeof(u64) * 8) { - printk(KERN_ERR "security: ebitmap: map size %u does not " + printk(KERN_ERR "SELinux: ebitmap: map size %u does not " "match my size %Zd (high bit was %d)\n", mapunit, sizeof(u64) * 8, e->highbit); goto bad; @@ -382,19 +382,19 @@ int ebitmap_read(struct ebitmap *e, void *fp) for (i = 0; i < count; i++) { rc = next_entry(&startbit, fp, sizeof(u32)); if (rc < 0) { - printk(KERN_ERR "security: ebitmap: truncated map\n"); + printk(KERN_ERR "SELinux: ebitmap: truncated map\n"); goto bad; } startbit = le32_to_cpu(startbit); if (startbit & (mapunit - 1)) { - printk(KERN_ERR "security: ebitmap start bit (%d) is " + printk(KERN_ERR "SELinux: ebitmap start bit (%d) is " "not a multiple of the map unit size (%u)\n", startbit, mapunit); goto bad; } if (startbit > e->highbit - mapunit) { - printk(KERN_ERR "security: ebitmap start bit (%d) is " + printk(KERN_ERR "SELinux: ebitmap start bit (%d) is " "beyond the end of the bitmap (%u)\n", startbit, (e->highbit - mapunit)); goto bad; @@ -405,7 +405,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); if (!tmp) { printk(KERN_ERR - "security: ebitmap: out of memory\n"); + "SELinux: ebitmap: out of memory\n"); rc = -ENOMEM; goto bad; } @@ -418,7 +418,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) } n = tmp; } else if (startbit <= n->startbit) { - printk(KERN_ERR "security: ebitmap: start bit %d" + printk(KERN_ERR "SELinux: ebitmap: start bit %d" " comes after start bit %d\n", startbit, n->startbit); goto bad; @@ -426,7 +426,7 @@ int ebitmap_read(struct ebitmap *e, void *fp) rc = next_entry(&map, fp, sizeof(u64)); if (rc < 0) { - printk(KERN_ERR "security: ebitmap: truncated map\n"); + printk(KERN_ERR "SELinux: ebitmap: truncated map\n"); goto bad; } map = le64_to_cpu(map); diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index bd7d6a00342..6bdb0ff6a92 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = { .version = POLICYDB_VERSION_POLCAP, .sym_num = SYM_NUM, .ocon_num = OCON_NUM, + }, + { + .version = POLICYDB_VERSION_PERMISSIVE, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, } }; @@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p) goto out_free_symtab; ebitmap_init(&p->policycaps); + ebitmap_init(&p->permissive_map); out: return rc; @@ -401,14 +407,14 @@ static int policydb_index_others(struct policydb *p) { int i, rc = 0; - printk(KERN_DEBUG "security: %d users, %d roles, %d types, %d bools", + printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); if (selinux_mls_enabled) printk(", %d sens, %d cats", p->p_levels.nprim, p->p_cats.nprim); printk("\n"); - printk(KERN_DEBUG "security: %d classes, %d rules\n", + printk(KERN_DEBUG "SELinux: %d classes, %d rules\n", p->p_classes.nprim, p->te_avtab.nel); #ifdef DEBUG_HASHES @@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p) kfree(p->type_attr_map); kfree(p->undefined_perms); ebitmap_destroy(&p->policycaps); + ebitmap_destroy(&p->permissive_map); return; } @@ -702,20 +709,20 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s) rc = sidtab_init(s); if (rc) { - printk(KERN_ERR "security: out of memory on SID table init\n"); + printk(KERN_ERR "SELinux: out of memory on SID table init\n"); goto out; } head = p->ocontexts[OCON_ISID]; for (c = head; c; c = c->next) { if (!c->context[0].user) { - printk(KERN_ERR "security: SID %s was never " + printk(KERN_ERR "SELinux: SID %s was never " "defined.\n", c->u.name); rc = -EINVAL; goto out; } if (sidtab_insert(s, c->sid[0], &c->context[0])) { - printk(KERN_ERR "security: unable to load initial " + printk(KERN_ERR "SELinux: unable to load initial " "SID %s.\n", c->u.name); rc = -EINVAL; goto out; @@ -809,13 +816,13 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) items = le32_to_cpu(buf[0]); if (items > ARRAY_SIZE(buf)) { - printk(KERN_ERR "security: mls: range overflow\n"); + printk(KERN_ERR "SELinux: mls: range overflow\n"); rc = -EINVAL; goto out; } rc = next_entry(buf, fp, sizeof(u32) * items); if (rc < 0) { - printk(KERN_ERR "security: mls: truncated range\n"); + printk(KERN_ERR "SELinux: mls: truncated range\n"); goto out; } r->level[0].sens = le32_to_cpu(buf[0]); @@ -826,21 +833,21 @@ static int mls_read_range_helper(struct mls_range *r, void *fp) rc = ebitmap_read(&r->level[0].cat, fp); if (rc) { - printk(KERN_ERR "security: mls: error reading low " + printk(KERN_ERR "SELinux: mls: error reading low " "categories\n"); goto out; } if (items > 1) { rc = ebitmap_read(&r->level[1].cat, fp); if (rc) { - printk(KERN_ERR "security: mls: error reading high " + printk(KERN_ERR "SELinux: mls: error reading high " "categories\n"); goto bad_high; } } else { rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat); if (rc) { - printk(KERN_ERR "security: mls: out of memory\n"); + printk(KERN_ERR "SELinux: mls: out of memory\n"); goto bad_high; } } @@ -866,7 +873,7 @@ static int context_read_and_validate(struct context *c, rc = next_entry(buf, fp, sizeof buf); if (rc < 0) { - printk(KERN_ERR "security: context truncated\n"); + printk(KERN_ERR "SELinux: context truncated\n"); goto out; } c->user = le32_to_cpu(buf[0]); @@ -874,7 +881,7 @@ static int context_read_and_validate(struct context *c, c->type = le32_to_cpu(buf[2]); if (p->policyvers >= POLICYDB_VERSION_MLS) { if (mls_read_range_helper(&c->range, fp)) { - printk(KERN_ERR "security: error reading MLS range of " + printk(KERN_ERR "SELinux: error reading MLS range of " "context\n"); rc = -EINVAL; goto out; @@ -882,7 +889,7 @@ static int context_read_and_validate(struct context *c, } if (!policydb_context_isvalid(p, c)) { - printk(KERN_ERR "security: invalid security context\n"); + printk(KERN_ERR "SELinux: invalid security context\n"); context_destroy(c); rc = -EINVAL; } @@ -1128,7 +1135,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey); if (!cladatum->comdatum) { - printk(KERN_ERR "security: unknown common %s\n", + printk(KERN_ERR "SELinux: unknown common %s\n", cladatum->comkey); rc = -EINVAL; goto bad; @@ -1283,13 +1290,13 @@ static int mls_read_level(struct mls_level *lp, void *fp) rc = next_entry(buf, fp, sizeof buf); if (rc < 0) { - printk(KERN_ERR "security: mls: truncated level\n"); + printk(KERN_ERR "SELinux: mls: truncated level\n"); goto bad; } lp->sens = le32_to_cpu(buf[0]); if (ebitmap_read(&lp->cat, fp)) { - printk(KERN_ERR "security: mls: error reading level " + printk(KERN_ERR "SELinux: mls: error reading level " "categories\n"); goto bad; } @@ -1491,7 +1498,7 @@ int policydb_read(struct policydb *p, void *fp) goto bad; if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { - printk(KERN_ERR "security: policydb magic number 0x%x does " + printk(KERN_ERR "SELinux: policydb magic number 0x%x does " "not match expected magic number 0x%x\n", le32_to_cpu(buf[0]), POLICYDB_MAGIC); goto bad; @@ -1499,27 +1506,27 @@ int policydb_read(struct policydb *p, void *fp) len = le32_to_cpu(buf[1]); if (len != strlen(POLICYDB_STRING)) { - printk(KERN_ERR "security: policydb string length %d does not " + printk(KERN_ERR "SELinux: policydb string length %d does not " "match expected length %Zu\n", len, strlen(POLICYDB_STRING)); goto bad; } policydb_str = kmalloc(len + 1,GFP_KERNEL); if (!policydb_str) { - printk(KERN_ERR "security: unable to allocate memory for policydb " + printk(KERN_ERR "SELinux: unable to allocate memory for policydb " "string of length %d\n", len); rc = -ENOMEM; goto bad; } rc = next_entry(policydb_str, fp, len); if (rc < 0) { - printk(KERN_ERR "security: truncated policydb string identifier\n"); + printk(KERN_ERR "SELinux: truncated policydb string identifier\n"); kfree(policydb_str); goto bad; } policydb_str[len] = 0; if (strcmp(policydb_str, POLICYDB_STRING)) { - printk(KERN_ERR "security: policydb string %s does not match " + printk(KERN_ERR "SELinux: policydb string %s does not match " "my string %s\n", policydb_str, POLICYDB_STRING); kfree(policydb_str); goto bad; @@ -1536,7 +1543,7 @@ int policydb_read(struct policydb *p, void *fp) p->policyvers = le32_to_cpu(buf[0]); if (p->policyvers < POLICYDB_VERSION_MIN || p->policyvers > POLICYDB_VERSION_MAX) { - printk(KERN_ERR "security: policydb version %d does not match " + printk(KERN_ERR "SELinux: policydb version %d does not match " "my version range %d-%d\n", le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); goto bad; @@ -1570,16 +1577,20 @@ int policydb_read(struct policydb *p, void *fp) ebitmap_read(&p->policycaps, fp) != 0) goto bad; + if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && + ebitmap_read(&p->permissive_map, fp) != 0) + goto bad; + info = policydb_lookup_compat(p->policyvers); if (!info) { - printk(KERN_ERR "security: unable to find policy compat info " + printk(KERN_ERR "SELinux: unable to find policy compat info " "for version %d\n", p->policyvers); goto bad; } if (le32_to_cpu(buf[2]) != info->sym_num || le32_to_cpu(buf[3]) != info->ocon_num) { - printk(KERN_ERR "security: policydb table sizes (%d,%d) do " + printk(KERN_ERR "SELinux: policydb table sizes (%d,%d) do " "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), le32_to_cpu(buf[3]), info->sym_num, info->ocon_num); @@ -1823,7 +1834,7 @@ int policydb_read(struct policydb *p, void *fp) for (genfs_p = NULL, genfs = p->genfs; genfs; genfs_p = genfs, genfs = genfs->next) { if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { - printk(KERN_ERR "security: dup genfs " + printk(KERN_ERR "SELinux: dup genfs " "fstype %s\n", newgenfs->fstype); kfree(newgenfs->fstype); kfree(newgenfs); @@ -1873,7 +1884,7 @@ int policydb_read(struct policydb *p, void *fp) if (!strcmp(newc->u.name, c->u.name) && (!c->v.sclass || !newc->v.sclass || newc->v.sclass == c->v.sclass)) { - printk(KERN_ERR "security: dup genfs " + printk(KERN_ERR "SELinux: dup genfs " "entry (%s,%s)\n", newgenfs->fstype, c->u.name); goto bad_newc; @@ -1931,7 +1942,7 @@ int policydb_read(struct policydb *p, void *fp) if (rc) goto bad; if (!mls_range_isvalid(p, &rt->target_range)) { - printk(KERN_WARNING "security: rangetrans: invalid range\n"); + printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); goto bad; } lrt = rt; diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index c4ce996e202..ba593a3da87 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -243,6 +243,8 @@ struct policydb { struct ebitmap policycaps; + struct ebitmap permissive_map; + unsigned int policyvers; unsigned int reject_unknown : 1; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 3f2bad28ee7..d75050819b0 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -40,6 +40,7 @@ #include <linux/sched.h> #include <linux/audit.h> #include <linux/mutex.h> +#include <linux/selinux.h> #include <net/netlabel.h> #include "flask.h" @@ -61,6 +62,7 @@ extern void selnl_notify_policyload(u32 seqno); unsigned int policydb_loaded_version; int selinux_policycap_netpeer; +int selinux_policycap_openperm; /* * This is declared in avc.c @@ -412,10 +414,35 @@ static int context_struct_compute_av(struct context *scontext, return 0; inval_class: - printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass); + printk(KERN_ERR "%s: unrecognized class %d\n", __func__, tclass); return -EINVAL; } +/* + * Given a sid find if the type has the permissive flag set + */ +int security_permissive_sid(u32 sid) +{ + struct context *context; + u32 type; + int rc; + + POLICY_RDLOCK; + + context = sidtab_search(&sidtab, sid); + BUG_ON(!context); + + type = context->type; + /* + * we are intentionally using type here, not type-1, the 0th bit may + * someday indicate that we are globally setting permissive in policy. + */ + rc = ebitmap_get_bit(&policydb.permissive_map, type); + + POLICY_RDUNLOCK; + return rc; +} + static int security_validtrans_handle_fail(struct context *ocontext, struct context *ncontext, struct context *tcontext, @@ -1096,7 +1123,7 @@ static int validate_classes(struct policydb *p) continue; if (i > p->p_classes.nprim) { printk(KERN_INFO - "security: class %s not defined in policy\n", + "SELinux: class %s not defined in policy\n", def_class); if (p->reject_unknown) return -EINVAL; @@ -1107,7 +1134,7 @@ static int validate_classes(struct policydb *p) pol_class = p->p_class_val_to_name[i-1]; if (strcmp(pol_class, def_class)) { printk(KERN_ERR - "security: class %d is incorrect, found %s but should be %s\n", + "SELinux: class %d is incorrect, found %s but should be %s\n", i, pol_class, def_class); return -EINVAL; } @@ -1125,7 +1152,7 @@ static int validate_classes(struct policydb *p) nprim = 1 << (perms->nprim - 1); if (perm_val > nprim) { printk(KERN_INFO - "security: permission %s in class %s not defined in policy\n", + "SELinux: permission %s in class %s not defined in policy\n", def_perm, pol_class); if (p->reject_unknown) return -EINVAL; @@ -1136,14 +1163,14 @@ static int validate_classes(struct policydb *p) perdatum = hashtab_search(perms->table, def_perm); if (perdatum == NULL) { printk(KERN_ERR - "security: permission %s in class %s not found in policy, bad policy\n", + "SELinux: permission %s in class %s not found in policy, bad policy\n", def_perm, pol_class); return -EINVAL; } pol_val = 1 << (perdatum->value - 1); if (pol_val != perm_val) { printk(KERN_ERR - "security: permission %s in class %s has incorrect value\n", + "SELinux: permission %s in class %s has incorrect value\n", def_perm, pol_class); return -EINVAL; } @@ -1157,7 +1184,7 @@ static int validate_classes(struct policydb *p) BUG_ON(!cladatum); if (!cladatum->comdatum) { printk(KERN_ERR - "security: class %s should have an inherits clause but does not\n", + "SELinux: class %s should have an inherits clause but does not\n", pol_class); return -EINVAL; } @@ -1172,7 +1199,7 @@ static int validate_classes(struct policydb *p) def_perm = kdefs->av_inherit[i].common_pts[j]; if (j >= perms->nprim) { printk(KERN_INFO - "security: permission %s in class %s not defined in policy\n", + "SELinux: permission %s in class %s not defined in policy\n", def_perm, pol_class); if (p->reject_unknown) return -EINVAL; @@ -1183,13 +1210,13 @@ static int validate_classes(struct policydb *p) perdatum = hashtab_search(perms->table, def_perm); if (perdatum == NULL) { printk(KERN_ERR - "security: permission %s in class %s not found in policy, bad policy\n", + "SELinux: permission %s in class %s not found in policy, bad policy\n", def_perm, pol_class); return -EINVAL; } if (perdatum->value != j + 1) { printk(KERN_ERR - "security: permission %s in class %s has incorrect value\n", + "SELinux: permission %s in class %s has incorrect value\n", def_perm, pol_class); return -EINVAL; } @@ -1219,7 +1246,7 @@ static inline int convert_context_handle_invalid_context(struct context *context u32 len; context_struct_to_string(context, &s, &len); - printk(KERN_ERR "security: context %s is invalid\n", s); + printk(KERN_ERR "SELinux: context %s is invalid\n", s); kfree(s); } return rc; @@ -1299,7 +1326,7 @@ out: bad: context_struct_to_string(&oldc, &s, &len); context_destroy(&oldc); - printk(KERN_ERR "security: invalidating context %s\n", s); + printk(KERN_ERR "SELinux: invalidating context %s\n", s); kfree(s); goto out; } @@ -1308,6 +1335,8 @@ static void security_load_policycaps(void) { selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps, POLICYDB_CAPABILITY_NETPEER); + selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps, + POLICYDB_CAPABILITY_OPENPERM); } extern void selinux_complete_init(void); @@ -1350,7 +1379,7 @@ int security_load_policy(void *data, size_t len) /* Verify that the kernel defined classes are correct. */ if (validate_classes(&policydb)) { printk(KERN_ERR - "security: the definition of a class is incorrect\n"); + "SELinux: the definition of a class is incorrect\n"); LOAD_UNLOCK; sidtab_destroy(&sidtab); policydb_destroy(&policydb); @@ -1384,14 +1413,14 @@ int security_load_policy(void *data, size_t len) /* Verify that the kernel defined classes are correct. */ if (validate_classes(&newpolicydb)) { printk(KERN_ERR - "security: the definition of a class is incorrect\n"); + "SELinux: the definition of a class is incorrect\n"); rc = -EINVAL; goto err; } rc = security_preserve_bools(&newpolicydb); if (rc) { - printk(KERN_ERR "security: unable to preserve booleans\n"); + printk(KERN_ERR "SELinux: unable to preserve booleans\n"); goto err; } @@ -1443,17 +1472,11 @@ err: /** * security_port_sid - Obtain the SID for a port. - * @domain: communication domain aka address family - * @type: socket type * @protocol: protocol number * @port: port number * @out_sid: security identifier */ -int security_port_sid(u16 domain, - u16 type, - u8 protocol, - u16 port, - u32 *out_sid) +int security_port_sid(u8 protocol, u16 port, u32 *out_sid) { struct ocontext *c; int rc = 0; @@ -2203,7 +2226,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms) match = hashtab_search(policydb.p_classes.table, class); if (!match) { printk(KERN_ERR "%s: unrecognized class %s\n", - __FUNCTION__, class); + __func__, class); rc = -EINVAL; goto out; } |