diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 199 |
1 files changed, 127 insertions, 72 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 0753b20e23fe..24e1b1885de7 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -14,13 +14,14 @@ | |||
14 | * <dgoeddel@trustedcs.com> | 14 | * <dgoeddel@trustedcs.com> |
15 | * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. | 15 | * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. |
16 | * Paul Moore, <paul.moore@hp.com> | 16 | * Paul Moore, <paul.moore@hp.com> |
17 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. | ||
18 | * Yuichi Nakamura <ynakam@hitachisoft.jp> | ||
17 | * | 19 | * |
18 | * This program is free software; you can redistribute it and/or modify | 20 | * This program is free software; you can redistribute it and/or modify |
19 | * it under the terms of the GNU General Public License version 2, | 21 | * it under the terms of the GNU General Public License version 2, |
20 | * as published by the Free Software Foundation. | 22 | * as published by the Free Software Foundation. |
21 | */ | 23 | */ |
22 | 24 | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
26 | #include <linux/ptrace.h> | 27 | #include <linux/ptrace.h> |
@@ -47,7 +48,7 @@ | |||
47 | #include <linux/netfilter_ipv6.h> | 48 | #include <linux/netfilter_ipv6.h> |
48 | #include <linux/tty.h> | 49 | #include <linux/tty.h> |
49 | #include <net/icmp.h> | 50 | #include <net/icmp.h> |
50 | #include <net/ip.h> /* for sysctl_local_port_range[] */ | 51 | #include <net/ip.h> /* for local_port_range[] */ |
51 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ | 52 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ |
52 | #include <asm/uaccess.h> | 53 | #include <asm/uaccess.h> |
53 | #include <asm/ioctls.h> | 54 | #include <asm/ioctls.h> |
@@ -84,6 +85,7 @@ | |||
84 | extern unsigned int policydb_loaded_version; | 85 | extern unsigned int policydb_loaded_version; |
85 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 86 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
86 | extern int selinux_compat_net; | 87 | extern int selinux_compat_net; |
88 | extern struct security_operations *security_ops; | ||
87 | 89 | ||
88 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP | 90 | #ifdef CONFIG_SECURITY_SELINUX_DEVELOP |
89 | int selinux_enforcing = 0; | 91 | int selinux_enforcing = 0; |
@@ -2295,6 +2297,25 @@ static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
2295 | return dentry_has_perm(current, mnt, dentry, FILE__GETATTR); | 2297 | return dentry_has_perm(current, mnt, dentry, FILE__GETATTR); |
2296 | } | 2298 | } |
2297 | 2299 | ||
2300 | static int selinux_inode_setotherxattr(struct dentry *dentry, char *name) | ||
2301 | { | ||
2302 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | ||
2303 | sizeof XATTR_SECURITY_PREFIX - 1)) { | ||
2304 | if (!strcmp(name, XATTR_NAME_CAPS)) { | ||
2305 | if (!capable(CAP_SETFCAP)) | ||
2306 | return -EPERM; | ||
2307 | } else if (!capable(CAP_SYS_ADMIN)) { | ||
2308 | /* A different attribute in the security namespace. | ||
2309 | Restrict to administrator. */ | ||
2310 | return -EPERM; | ||
2311 | } | ||
2312 | } | ||
2313 | |||
2314 | /* Not an attribute we recognize, so just check the | ||
2315 | ordinary setattr permission. */ | ||
2316 | return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); | ||
2317 | } | ||
2318 | |||
2298 | static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags) | 2319 | static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags) |
2299 | { | 2320 | { |
2300 | struct task_security_struct *tsec = current->security; | 2321 | struct task_security_struct *tsec = current->security; |
@@ -2305,19 +2326,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value | |||
2305 | u32 newsid; | 2326 | u32 newsid; |
2306 | int rc = 0; | 2327 | int rc = 0; |
2307 | 2328 | ||
2308 | if (strcmp(name, XATTR_NAME_SELINUX)) { | 2329 | if (strcmp(name, XATTR_NAME_SELINUX)) |
2309 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 2330 | return selinux_inode_setotherxattr(dentry, name); |
2310 | sizeof XATTR_SECURITY_PREFIX - 1) && | ||
2311 | !capable(CAP_SYS_ADMIN)) { | ||
2312 | /* A different attribute in the security namespace. | ||
2313 | Restrict to administrator. */ | ||
2314 | return -EPERM; | ||
2315 | } | ||
2316 | |||
2317 | /* Not an attribute we recognize, so just check the | ||
2318 | ordinary setattr permission. */ | ||
2319 | return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); | ||
2320 | } | ||
2321 | 2331 | ||
2322 | sbsec = inode->i_sb->s_security; | 2332 | sbsec = inode->i_sb->s_security; |
2323 | if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) | 2333 | if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) |
@@ -2391,31 +2401,14 @@ static int selinux_inode_listxattr (struct dentry *dentry) | |||
2391 | 2401 | ||
2392 | static int selinux_inode_removexattr (struct dentry *dentry, char *name) | 2402 | static int selinux_inode_removexattr (struct dentry *dentry, char *name) |
2393 | { | 2403 | { |
2394 | if (strcmp(name, XATTR_NAME_SELINUX)) { | 2404 | if (strcmp(name, XATTR_NAME_SELINUX)) |
2395 | if (!strncmp(name, XATTR_SECURITY_PREFIX, | 2405 | return selinux_inode_setotherxattr(dentry, name); |
2396 | sizeof XATTR_SECURITY_PREFIX - 1) && | ||
2397 | !capable(CAP_SYS_ADMIN)) { | ||
2398 | /* A different attribute in the security namespace. | ||
2399 | Restrict to administrator. */ | ||
2400 | return -EPERM; | ||
2401 | } | ||
2402 | |||
2403 | /* Not an attribute we recognize, so just check the | ||
2404 | ordinary setattr permission. Might want a separate | ||
2405 | permission for removexattr. */ | ||
2406 | return dentry_has_perm(current, NULL, dentry, FILE__SETATTR); | ||
2407 | } | ||
2408 | 2406 | ||
2409 | /* No one is allowed to remove a SELinux security label. | 2407 | /* No one is allowed to remove a SELinux security label. |
2410 | You can change the label, but all data must be labeled. */ | 2408 | You can change the label, but all data must be labeled. */ |
2411 | return -EACCES; | 2409 | return -EACCES; |
2412 | } | 2410 | } |
2413 | 2411 | ||
2414 | static const char *selinux_inode_xattr_getsuffix(void) | ||
2415 | { | ||
2416 | return XATTR_SELINUX_SUFFIX; | ||
2417 | } | ||
2418 | |||
2419 | /* | 2412 | /* |
2420 | * Copy the in-core inode security context value to the user. If the | 2413 | * Copy the in-core inode security context value to the user. If the |
2421 | * getxattr() prior to this succeeded, check to see if we need to | 2414 | * getxattr() prior to this succeeded, check to see if we need to |
@@ -2462,9 +2455,19 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t | |||
2462 | return len; | 2455 | return len; |
2463 | } | 2456 | } |
2464 | 2457 | ||
2458 | static int selinux_inode_need_killpriv(struct dentry *dentry) | ||
2459 | { | ||
2460 | return secondary_ops->inode_need_killpriv(dentry); | ||
2461 | } | ||
2462 | |||
2463 | static int selinux_inode_killpriv(struct dentry *dentry) | ||
2464 | { | ||
2465 | return secondary_ops->inode_killpriv(dentry); | ||
2466 | } | ||
2467 | |||
2465 | /* file security operations */ | 2468 | /* file security operations */ |
2466 | 2469 | ||
2467 | static int selinux_file_permission(struct file *file, int mask) | 2470 | static int selinux_revalidate_file_permission(struct file *file, int mask) |
2468 | { | 2471 | { |
2469 | int rc; | 2472 | int rc; |
2470 | struct inode *inode = file->f_path.dentry->d_inode; | 2473 | struct inode *inode = file->f_path.dentry->d_inode; |
@@ -2486,6 +2489,25 @@ static int selinux_file_permission(struct file *file, int mask) | |||
2486 | return selinux_netlbl_inode_permission(inode, mask); | 2489 | return selinux_netlbl_inode_permission(inode, mask); |
2487 | } | 2490 | } |
2488 | 2491 | ||
2492 | static int selinux_file_permission(struct file *file, int mask) | ||
2493 | { | ||
2494 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2495 | struct task_security_struct *tsec = current->security; | ||
2496 | struct file_security_struct *fsec = file->f_security; | ||
2497 | struct inode_security_struct *isec = inode->i_security; | ||
2498 | |||
2499 | if (!mask) { | ||
2500 | /* No permission to check. Existence test. */ | ||
2501 | return 0; | ||
2502 | } | ||
2503 | |||
2504 | if (tsec->sid == fsec->sid && fsec->isid == isec->sid | ||
2505 | && fsec->pseqno == avc_policy_seqno()) | ||
2506 | return selinux_netlbl_inode_permission(inode, mask); | ||
2507 | |||
2508 | return selinux_revalidate_file_permission(file, mask); | ||
2509 | } | ||
2510 | |||
2489 | static int selinux_file_alloc_security(struct file *file) | 2511 | static int selinux_file_alloc_security(struct file *file) |
2490 | { | 2512 | { |
2491 | return file_alloc_security(file); | 2513 | return file_alloc_security(file); |
@@ -2725,6 +2747,34 @@ static int selinux_file_receive(struct file *file) | |||
2725 | return file_has_perm(current, file, file_to_av(file)); | 2747 | return file_has_perm(current, file, file_to_av(file)); |
2726 | } | 2748 | } |
2727 | 2749 | ||
2750 | static int selinux_dentry_open(struct file *file) | ||
2751 | { | ||
2752 | struct file_security_struct *fsec; | ||
2753 | struct inode *inode; | ||
2754 | struct inode_security_struct *isec; | ||
2755 | inode = file->f_path.dentry->d_inode; | ||
2756 | fsec = file->f_security; | ||
2757 | isec = inode->i_security; | ||
2758 | /* | ||
2759 | * Save inode label and policy sequence number | ||
2760 | * at open-time so that selinux_file_permission | ||
2761 | * can determine whether revalidation is necessary. | ||
2762 | * Task label is already saved in the file security | ||
2763 | * struct as its SID. | ||
2764 | */ | ||
2765 | fsec->isid = isec->sid; | ||
2766 | fsec->pseqno = avc_policy_seqno(); | ||
2767 | /* | ||
2768 | * Since the inode label or policy seqno may have changed | ||
2769 | * between the selinux_inode_permission check and the saving | ||
2770 | * of state above, recheck that access is still permitted. | ||
2771 | * Otherwise, access might never be revalidated against the | ||
2772 | * new inode label or new policy. | ||
2773 | * This check is not redundant - do not remove. | ||
2774 | */ | ||
2775 | return inode_has_perm(current, inode, file_to_av(file), NULL); | ||
2776 | } | ||
2777 | |||
2728 | /* task security operations */ | 2778 | /* task security operations */ |
2729 | 2779 | ||
2730 | static int selinux_task_create(unsigned long clone_flags) | 2780 | static int selinux_task_create(unsigned long clone_flags) |
@@ -2833,6 +2883,12 @@ static int selinux_task_setnice(struct task_struct *p, int nice) | |||
2833 | 2883 | ||
2834 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) | 2884 | static int selinux_task_setioprio(struct task_struct *p, int ioprio) |
2835 | { | 2885 | { |
2886 | int rc; | ||
2887 | |||
2888 | rc = secondary_ops->task_setioprio(p, ioprio); | ||
2889 | if (rc) | ||
2890 | return rc; | ||
2891 | |||
2836 | return task_has_perm(current, p, PROCESS__SETSCHED); | 2892 | return task_has_perm(current, p, PROCESS__SETSCHED); |
2837 | } | 2893 | } |
2838 | 2894 | ||
@@ -2862,6 +2918,12 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim | |||
2862 | 2918 | ||
2863 | static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) | 2919 | static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) |
2864 | { | 2920 | { |
2921 | int rc; | ||
2922 | |||
2923 | rc = secondary_ops->task_setscheduler(p, policy, lp); | ||
2924 | if (rc) | ||
2925 | return rc; | ||
2926 | |||
2865 | return task_has_perm(current, p, PROCESS__SETSCHED); | 2927 | return task_has_perm(current, p, PROCESS__SETSCHED); |
2866 | } | 2928 | } |
2867 | 2929 | ||
@@ -3232,8 +3294,6 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3232 | /* Range of port numbers used to automatically bind. | 3294 | /* Range of port numbers used to automatically bind. |
3233 | Need to determine whether we should perform a name_bind | 3295 | Need to determine whether we should perform a name_bind |
3234 | permission check between the socket and the port number. */ | 3296 | permission check between the socket and the port number. */ |
3235 | #define ip_local_port_range_0 sysctl_local_port_range[0] | ||
3236 | #define ip_local_port_range_1 sysctl_local_port_range[1] | ||
3237 | 3297 | ||
3238 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3298 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3239 | { | 3299 | { |
@@ -3276,20 +3336,27 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3276 | addrp = (char *)&addr6->sin6_addr.s6_addr; | 3336 | addrp = (char *)&addr6->sin6_addr.s6_addr; |
3277 | } | 3337 | } |
3278 | 3338 | ||
3279 | if (snum&&(snum < max(PROT_SOCK,ip_local_port_range_0) || | 3339 | if (snum) { |
3280 | snum > ip_local_port_range_1)) { | 3340 | int low, high; |
3281 | err = security_port_sid(sk->sk_family, sk->sk_type, | 3341 | |
3282 | sk->sk_protocol, snum, &sid); | 3342 | inet_get_local_port_range(&low, &high); |
3283 | if (err) | 3343 | |
3284 | goto out; | 3344 | if (snum < max(PROT_SOCK, low) || snum > high) { |
3285 | AVC_AUDIT_DATA_INIT(&ad,NET); | 3345 | err = security_port_sid(sk->sk_family, |
3286 | ad.u.net.sport = htons(snum); | 3346 | sk->sk_type, |
3287 | ad.u.net.family = family; | 3347 | sk->sk_protocol, snum, |
3288 | err = avc_has_perm(isec->sid, sid, | 3348 | &sid); |
3289 | isec->sclass, | 3349 | if (err) |
3290 | SOCKET__NAME_BIND, &ad); | 3350 | goto out; |
3291 | if (err) | 3351 | AVC_AUDIT_DATA_INIT(&ad,NET); |
3292 | goto out; | 3352 | ad.u.net.sport = htons(snum); |
3353 | ad.u.net.family = family; | ||
3354 | err = avc_has_perm(isec->sid, sid, | ||
3355 | isec->sclass, | ||
3356 | SOCKET__NAME_BIND, &ad); | ||
3357 | if (err) | ||
3358 | goto out; | ||
3359 | } | ||
3293 | } | 3360 | } |
3294 | 3361 | ||
3295 | switch(isec->sclass) { | 3362 | switch(isec->sclass) { |
@@ -3927,7 +3994,7 @@ out: | |||
3927 | } | 3994 | } |
3928 | 3995 | ||
3929 | static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | 3996 | static unsigned int selinux_ip_postroute_last(unsigned int hooknum, |
3930 | struct sk_buff **pskb, | 3997 | struct sk_buff *skb, |
3931 | const struct net_device *in, | 3998 | const struct net_device *in, |
3932 | const struct net_device *out, | 3999 | const struct net_device *out, |
3933 | int (*okfn)(struct sk_buff *), | 4000 | int (*okfn)(struct sk_buff *), |
@@ -3936,7 +4003,6 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum, | |||
3936 | char *addrp; | 4003 | char *addrp; |
3937 | int len, err = 0; | 4004 | int len, err = 0; |
3938 | struct sock *sk; | 4005 | struct sock *sk; |
3939 | struct sk_buff *skb = *pskb; | ||
3940 | struct avc_audit_data ad; | 4006 | struct avc_audit_data ad; |
3941 | struct net_device *dev = (struct net_device *)out; | 4007 | struct net_device *dev = (struct net_device *)out; |
3942 | struct sk_security_struct *sksec; | 4008 | struct sk_security_struct *sksec; |
@@ -3972,23 +4038,23 @@ out: | |||
3972 | } | 4038 | } |
3973 | 4039 | ||
3974 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, | 4040 | static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, |
3975 | struct sk_buff **pskb, | 4041 | struct sk_buff *skb, |
3976 | const struct net_device *in, | 4042 | const struct net_device *in, |
3977 | const struct net_device *out, | 4043 | const struct net_device *out, |
3978 | int (*okfn)(struct sk_buff *)) | 4044 | int (*okfn)(struct sk_buff *)) |
3979 | { | 4045 | { |
3980 | return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET); | 4046 | return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET); |
3981 | } | 4047 | } |
3982 | 4048 | ||
3983 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 4049 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
3984 | 4050 | ||
3985 | static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, | 4051 | static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, |
3986 | struct sk_buff **pskb, | 4052 | struct sk_buff *skb, |
3987 | const struct net_device *in, | 4053 | const struct net_device *in, |
3988 | const struct net_device *out, | 4054 | const struct net_device *out, |
3989 | int (*okfn)(struct sk_buff *)) | 4055 | int (*okfn)(struct sk_buff *)) |
3990 | { | 4056 | { |
3991 | return selinux_ip_postroute_last(hooknum, pskb, in, out, okfn, PF_INET6); | 4057 | return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6); |
3992 | } | 4058 | } |
3993 | 4059 | ||
3994 | #endif /* IPV6 */ | 4060 | #endif /* IPV6 */ |
@@ -4483,19 +4549,6 @@ static int selinux_register_security (const char *name, struct security_operatio | |||
4483 | return 0; | 4549 | return 0; |
4484 | } | 4550 | } |
4485 | 4551 | ||
4486 | static int selinux_unregister_security (const char *name, struct security_operations *ops) | ||
4487 | { | ||
4488 | if (ops != secondary_ops) { | ||
4489 | printk(KERN_ERR "%s: trying to unregister a security module " | ||
4490 | "that is not registered.\n", __FUNCTION__); | ||
4491 | return -EINVAL; | ||
4492 | } | ||
4493 | |||
4494 | secondary_ops = original_ops; | ||
4495 | |||
4496 | return 0; | ||
4497 | } | ||
4498 | |||
4499 | static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode) | 4552 | static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode) |
4500 | { | 4553 | { |
4501 | if (inode) | 4554 | if (inode) |
@@ -4773,10 +4826,11 @@ static struct security_operations selinux_ops = { | |||
4773 | .inode_getxattr = selinux_inode_getxattr, | 4826 | .inode_getxattr = selinux_inode_getxattr, |
4774 | .inode_listxattr = selinux_inode_listxattr, | 4827 | .inode_listxattr = selinux_inode_listxattr, |
4775 | .inode_removexattr = selinux_inode_removexattr, | 4828 | .inode_removexattr = selinux_inode_removexattr, |
4776 | .inode_xattr_getsuffix = selinux_inode_xattr_getsuffix, | ||
4777 | .inode_getsecurity = selinux_inode_getsecurity, | 4829 | .inode_getsecurity = selinux_inode_getsecurity, |
4778 | .inode_setsecurity = selinux_inode_setsecurity, | 4830 | .inode_setsecurity = selinux_inode_setsecurity, |
4779 | .inode_listsecurity = selinux_inode_listsecurity, | 4831 | .inode_listsecurity = selinux_inode_listsecurity, |
4832 | .inode_need_killpriv = selinux_inode_need_killpriv, | ||
4833 | .inode_killpriv = selinux_inode_killpriv, | ||
4780 | 4834 | ||
4781 | .file_permission = selinux_file_permission, | 4835 | .file_permission = selinux_file_permission, |
4782 | .file_alloc_security = selinux_file_alloc_security, | 4836 | .file_alloc_security = selinux_file_alloc_security, |
@@ -4790,6 +4844,8 @@ static struct security_operations selinux_ops = { | |||
4790 | .file_send_sigiotask = selinux_file_send_sigiotask, | 4844 | .file_send_sigiotask = selinux_file_send_sigiotask, |
4791 | .file_receive = selinux_file_receive, | 4845 | .file_receive = selinux_file_receive, |
4792 | 4846 | ||
4847 | .dentry_open = selinux_dentry_open, | ||
4848 | |||
4793 | .task_create = selinux_task_create, | 4849 | .task_create = selinux_task_create, |
4794 | .task_alloc_security = selinux_task_alloc_security, | 4850 | .task_alloc_security = selinux_task_alloc_security, |
4795 | .task_free_security = selinux_task_free_security, | 4851 | .task_free_security = selinux_task_free_security, |
@@ -4839,7 +4895,6 @@ static struct security_operations selinux_ops = { | |||
4839 | .sem_semop = selinux_sem_semop, | 4895 | .sem_semop = selinux_sem_semop, |
4840 | 4896 | ||
4841 | .register_security = selinux_register_security, | 4897 | .register_security = selinux_register_security, |
4842 | .unregister_security = selinux_unregister_security, | ||
4843 | 4898 | ||
4844 | .d_instantiate = selinux_d_instantiate, | 4899 | .d_instantiate = selinux_d_instantiate, |
4845 | 4900 | ||