Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
security: unexport mmap_min_addr
SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel
security: Protection for exploiting null dereference using mmap
SELinux: Use %lu for inode->i_no when printing avc
SELinux: allow preemption between transition permission checks
selinux: introduce schedule points in policydb_destroy()
selinux: add selinuxfs structure for object class discovery
selinux: change sel_make_dir() to specify inode counter.
selinux: rename sel_remove_bools() for more general usage.
selinux: add support for querying object classes and permissions from the running policy

+504 -86
+15
Documentation/sysctl/vm.txt
··· 31 31 - min_unmapped_ratio 32 32 - min_slab_ratio 33 33 - panic_on_oom 34 + - mmap_min_address 34 35 35 36 ============================================================== 36 37 ··· 217 216 The default value is 0. 218 217 1 and 2 are for failover of clustering. Please select either 219 218 according to your policy of failover. 219 + 220 + ============================================================== 221 + 222 + mmap_min_addr 223 + 224 + This file indicates the amount of address space which a user process will 225 + be restricted from mmaping. Since kernel null dereference bugs could 226 + accidentally operate based on the information in the first couple of pages 227 + of memory userspace processes should not be allowed to write to them. By 228 + default this value is set to 0 and no protections will be enforced by the 229 + security module. Setting this value to something like 64k will allow the 230 + vast majority of applications to work correctly and provide defense in depth 231 + against future potential kernel bugs. 232 +
+12 -5
include/linux/security.h
··· 71 71 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb); 72 72 extern int cap_netlink_recv(struct sk_buff *skb, int cap); 73 73 74 + extern unsigned long mmap_min_addr; 74 75 /* 75 76 * Values used in the task_security_ops calls 76 77 */ ··· 1242 1241 int (*file_ioctl) (struct file * file, unsigned int cmd, 1243 1242 unsigned long arg); 1244 1243 int (*file_mmap) (struct file * file, 1245 - unsigned long reqprot, 1246 - unsigned long prot, unsigned long flags); 1244 + unsigned long reqprot, unsigned long prot, 1245 + unsigned long flags, unsigned long addr, 1246 + unsigned long addr_only); 1247 1247 int (*file_mprotect) (struct vm_area_struct * vma, 1248 1248 unsigned long reqprot, 1249 1249 unsigned long prot); ··· 1816 1814 1817 1815 static inline int security_file_mmap (struct file *file, unsigned long reqprot, 1818 1816 unsigned long prot, 1819 - unsigned long flags) 1817 + unsigned long flags, 1818 + unsigned long addr, 1819 + unsigned long addr_only) 1820 1820 { 1821 - return security_ops->file_mmap (file, reqprot, prot, flags); 1821 + return security_ops->file_mmap (file, reqprot, prot, flags, addr, 1822 + addr_only); 1822 1823 } 1823 1824 1824 1825 static inline int security_file_mprotect (struct vm_area_struct *vma, ··· 2494 2489 2495 2490 static inline int security_file_mmap (struct file *file, unsigned long reqprot, 2496 2491 unsigned long prot, 2497 - unsigned long flags) 2492 + unsigned long flags, 2493 + unsigned long addr, 2494 + unsigned long addr_only) 2498 2495 { 2499 2496 return 0; 2500 2497 }
+10
kernel/sysctl.c
··· 949 949 .strategy = &sysctl_jiffies, 950 950 }, 951 951 #endif 952 + #ifdef CONFIG_SECURITY 953 + { 954 + .ctl_name = CTL_UNNUMBERED, 955 + .procname = "mmap_min_addr", 956 + .data = &mmap_min_addr, 957 + .maxlen = sizeof(unsigned long), 958 + .mode = 0644, 959 + .proc_handler = &proc_doulongvec_minmax, 960 + }, 961 + #endif 952 962 #if defined(CONFIG_X86_32) || \ 953 963 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) 954 964 {
+2 -2
mm/mmap.c
··· 1023 1023 } 1024 1024 } 1025 1025 1026 - error = security_file_mmap(file, reqprot, prot, flags); 1026 + error = security_file_mmap(file, reqprot, prot, flags, addr, 0); 1027 1027 if (error) 1028 1028 return error; 1029 - 1029 + 1030 1030 /* Clear old maps */ 1031 1031 error = -ENOMEM; 1032 1032 munmap_back:
+11 -2
mm/mremap.c
··· 291 291 if ((addr <= new_addr) && (addr+old_len) > new_addr) 292 292 goto out; 293 293 294 + ret = security_file_mmap(0, 0, 0, 0, new_addr, 1); 295 + if (ret) 296 + goto out; 297 + 294 298 ret = do_munmap(mm, new_addr, new_len); 295 299 if (ret) 296 300 goto out; ··· 394 390 395 391 new_addr = get_unmapped_area(vma->vm_file, 0, new_len, 396 392 vma->vm_pgoff, map_flags); 397 - ret = new_addr; 398 - if (new_addr & ~PAGE_MASK) 393 + if (new_addr & ~PAGE_MASK) { 394 + ret = new_addr; 395 + goto out; 396 + } 397 + 398 + ret = security_file_mmap(0, 0, 0, 0, new_addr, 1); 399 + if (ret) 399 400 goto out; 400 401 } 401 402 ret = move_vma(vma, addr, old_len, new_len, new_addr);
+1 -1
mm/nommu.c
··· 639 639 } 640 640 641 641 /* allow the security API to have its say */ 642 - ret = security_file_mmap(file, reqprot, prot, flags); 642 + ret = security_file_mmap(file, reqprot, prot, flags, addr, 0); 643 643 if (ret < 0) 644 644 return ret; 645 645
+5 -1
security/dummy.c
··· 420 420 421 421 static int dummy_file_mmap (struct file *file, unsigned long reqprot, 422 422 unsigned long prot, 423 - unsigned long flags) 423 + unsigned long flags, 424 + unsigned long addr, 425 + unsigned long addr_only) 424 426 { 427 + if (addr < mmap_min_addr) 428 + return -EACCES; 425 429 return 0; 426 430 } 427 431
+1
security/security.c
··· 24 24 extern void security_fixup_ops(struct security_operations *ops); 25 25 26 26 struct security_operations *security_ops; /* Initialized to NULL */ 27 + unsigned long mmap_min_addr; /* 0 means no protection */ 27 28 28 29 static inline int verify(struct security_operations *ops) 29 30 {
+7 -5
security/selinux/avc.c
··· 586 586 } 587 587 } 588 588 if (inode) 589 - audit_log_format(ab, " dev=%s ino=%ld", 589 + audit_log_format(ab, " dev=%s ino=%lu", 590 590 inode->i_sb->s_id, 591 591 inode->i_ino); 592 592 break; ··· 832 832 * @tsid: target security identifier 833 833 * @tclass: target security class 834 834 * @requested: requested permissions, interpreted based on @tclass 835 + * @flags: AVC_STRICT or 0 835 836 * @avd: access vector decisions 836 837 * 837 838 * Check the AVC to determine whether the @requested permissions are granted ··· 847 846 * should be released for the auditing. 848 847 */ 849 848 int avc_has_perm_noaudit(u32 ssid, u32 tsid, 850 - u16 tclass, u32 requested, 851 - struct av_decision *avd) 849 + u16 tclass, u32 requested, 850 + unsigned flags, 851 + struct av_decision *avd) 852 852 { 853 853 struct avc_node *node; 854 854 struct avc_entry entry, *p_ae; ··· 876 874 denied = requested & ~(p_ae->avd.allowed); 877 875 878 876 if (!requested || denied) { 879 - if (selinux_enforcing) 877 + if (selinux_enforcing || (flags & AVC_STRICT)) 880 878 rc = -EACCES; 881 879 else 882 880 if (node) ··· 911 909 struct av_decision avd; 912 910 int rc; 913 911 914 - rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd); 912 + rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); 915 913 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); 916 914 return rc; 917 915 }
+24 -18
security/selinux/hooks.c
··· 1592 1592 rc = secondary_ops->capable(current, CAP_SYS_ADMIN); 1593 1593 if (rc == 0) 1594 1594 rc = avc_has_perm_noaudit(tsec->sid, tsec->sid, 1595 - SECCLASS_CAPABILITY, 1596 - CAP_TO_MASK(CAP_SYS_ADMIN), 1597 - NULL); 1595 + SECCLASS_CAPABILITY, 1596 + CAP_TO_MASK(CAP_SYS_ADMIN), 1597 + 0, 1598 + NULL); 1598 1599 1599 1600 if (rc == 0) 1600 1601 cap_sys_admin = 1; ··· 2569 2568 } 2570 2569 2571 2570 static int selinux_file_mmap(struct file *file, unsigned long reqprot, 2572 - unsigned long prot, unsigned long flags) 2571 + unsigned long prot, unsigned long flags, 2572 + unsigned long addr, unsigned long addr_only) 2573 2573 { 2574 - int rc; 2574 + int rc = 0; 2575 + u32 sid = ((struct task_security_struct*)(current->security))->sid; 2575 2576 2576 - rc = secondary_ops->file_mmap(file, reqprot, prot, flags); 2577 - if (rc) 2577 + if (addr < mmap_min_addr) 2578 + rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, 2579 + MEMPROTECT__MMAP_ZERO, NULL); 2580 + if (rc || addr_only) 2578 2581 return rc; 2579 2582 2580 2583 if (selinux_checkreqprot) ··· 3129 3124 /** 3130 3125 * selinux_skb_extlbl_sid - Determine the external label of a packet 3131 3126 * @skb: the packet 3132 - * @base_sid: the SELinux SID to use as a context for MLS only external labels 3133 3127 * @sid: the packet's SID 3134 3128 * 3135 3129 * Description: 3136 3130 * Check the various different forms of external packet labeling and determine 3137 - * the external SID for the packet. 3131 + * the external SID for the packet. If only one form of external labeling is 3132 + * present then it is used, if both labeled IPsec and NetLabel labels are 3133 + * present then the SELinux type information is taken from the labeled IPsec 3134 + * SA and the MLS sensitivity label information is taken from the NetLabel 3135 + * security attributes. This bit of "magic" is done in the call to 3136 + * selinux_netlbl_skbuff_getsid(). 3138 3137 * 3139 3138 */ 3140 - static void selinux_skb_extlbl_sid(struct sk_buff *skb, 3141 - u32 base_sid, 3142 - u32 *sid) 3139 + static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) 3143 3140 { 3144 3141 u32 xfrm_sid; 3145 3142 u32 nlbl_sid; ··· 3149 3142 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3150 3143 if (selinux_netlbl_skbuff_getsid(skb, 3151 3144 (xfrm_sid == SECSID_NULL ? 3152 - base_sid : xfrm_sid), 3145 + SECINITSID_NETMSG : xfrm_sid), 3153 3146 &nlbl_sid) != 0) 3154 3147 nlbl_sid = SECSID_NULL; 3155 - 3156 3148 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); 3157 3149 } 3158 3150 ··· 3696 3690 if (sock && sock->sk->sk_family == PF_UNIX) 3697 3691 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 3698 3692 else if (skb) 3699 - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid); 3693 + selinux_skb_extlbl_sid(skb, &peer_secid); 3700 3694 3701 3695 if (peer_secid == SECSID_NULL) 3702 3696 err = -EINVAL; ··· 3757 3751 u32 newsid; 3758 3752 u32 peersid; 3759 3753 3760 - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid); 3754 + selinux_skb_extlbl_sid(skb, &peersid); 3761 3755 if (peersid == SECSID_NULL) { 3762 3756 req->secid = sksec->sid; 3763 3757 req->peer_secid = SECSID_NULL; ··· 3795 3789 { 3796 3790 struct sk_security_struct *sksec = sk->sk_security; 3797 3791 3798 - selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid); 3792 + selinux_skb_extlbl_sid(skb, &sksec->peer_sid); 3799 3793 } 3800 3794 3801 3795 static void selinux_req_classify_flow(const struct request_sock *req, ··· 4632 4626 if (p->ptrace & PT_PTRACED) { 4633 4627 error = avc_has_perm_noaudit(tsec->ptrace_sid, sid, 4634 4628 SECCLASS_PROCESS, 4635 - PROCESS__PTRACE, &avd); 4629 + PROCESS__PTRACE, 0, &avd); 4636 4630 if (!error) 4637 4631 tsec->sid = sid; 4638 4632 task_unlock(p);
+1
security/selinux/include/av_perm_to_string.h
··· 158 158 S_(SECCLASS_KEY, KEY__CREATE, "create") 159 159 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") 160 160 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") 161 + S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
+1
security/selinux/include/av_permissions.h
··· 823 823 #define DCCP_SOCKET__NAME_BIND 0x00200000UL 824 824 #define DCCP_SOCKET__NODE_BIND 0x00400000UL 825 825 #define DCCP_SOCKET__NAME_CONNECT 0x00800000UL 826 + #define MEMPROTECT__MMAP_ZERO 0x00000001UL
+4 -2
security/selinux/include/avc.h
··· 102 102 u16 tclass, u32 requested, 103 103 struct av_decision *avd, int result, struct avc_audit_data *auditdata); 104 104 105 + #define AVC_STRICT 1 /* Ignore permissive mode. */ 105 106 int avc_has_perm_noaudit(u32 ssid, u32 tsid, 106 - u16 tclass, u32 requested, 107 - struct av_decision *avd); 107 + u16 tclass, u32 requested, 108 + unsigned flags, 109 + struct av_decision *avd); 108 110 109 111 int avc_has_perm(u32 ssid, u32 tsid, 110 112 u16 tclass, u32 requested,
+1
security/selinux/include/class_to_string.h
··· 63 63 S_("key") 64 64 S_(NULL) 65 65 S_("dccp_socket") 66 + S_("memprotect")
+1
security/selinux/include/flask.h
··· 49 49 #define SECCLASS_PACKET 57 50 50 #define SECCLASS_KEY 58 51 51 #define SECCLASS_DCCP_SOCKET 60 52 + #define SECCLASS_MEMPROTECT 61 52 53 53 54 /* 54 55 * Security identifier indices for initial entities
+4
security/selinux/include/security.h
··· 41 41 42 42 int security_load_policy(void * data, size_t len); 43 43 44 + #define SEL_VEC_MAX 32 44 45 struct av_decision { 45 46 u32 allowed; 46 47 u32 decided; ··· 87 86 u16 tclass); 88 87 89 88 int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 89 + 90 + int security_get_classes(char ***classes, int *nclasses); 91 + int security_get_permissions(char *class, char ***perms, int *nperms); 90 92 91 93 #define SECURITY_FS_USE_XATTR 1 /* use xattr */ 92 94 #define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
+13 -21
security/selinux/netlabel.c
··· 158 158 netlbl_secattr_init(&secattr); 159 159 rc = netlbl_skbuff_getattr(skb, &secattr); 160 160 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) 161 - rc = security_netlbl_secattr_to_sid(&secattr, 162 - base_sid, 163 - sid); 161 + rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); 164 162 else 165 163 *sid = SECSID_NULL; 166 164 netlbl_secattr_destroy(&secattr); ··· 196 198 if (netlbl_sock_getattr(sk, &secattr) == 0 && 197 199 secattr.flags != NETLBL_SECATTR_NONE && 198 200 security_netlbl_secattr_to_sid(&secattr, 199 - SECINITSID_UNLABELED, 201 + SECINITSID_NETMSG, 200 202 &nlbl_peer_sid) == 0) 201 203 sksec->peer_sid = nlbl_peer_sid; 202 204 netlbl_secattr_destroy(&secattr); ··· 293 295 struct avc_audit_data *ad) 294 296 { 295 297 int rc; 296 - u32 netlbl_sid; 297 - u32 recv_perm; 298 + u32 nlbl_sid; 299 + u32 perm; 298 300 299 - rc = selinux_netlbl_skbuff_getsid(skb, 300 - SECINITSID_UNLABELED, 301 - &netlbl_sid); 301 + rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &nlbl_sid); 302 302 if (rc != 0) 303 303 return rc; 304 - 305 - if (netlbl_sid == SECSID_NULL) 306 - return 0; 304 + if (nlbl_sid == SECSID_NULL) 305 + nlbl_sid = SECINITSID_UNLABELED; 307 306 308 307 switch (sksec->sclass) { 309 308 case SECCLASS_UDP_SOCKET: 310 - recv_perm = UDP_SOCKET__RECVFROM; 309 + perm = UDP_SOCKET__RECVFROM; 311 310 break; 312 311 case SECCLASS_TCP_SOCKET: 313 - recv_perm = TCP_SOCKET__RECVFROM; 312 + perm = TCP_SOCKET__RECVFROM; 314 313 break; 315 314 default: 316 - recv_perm = RAWIP_SOCKET__RECVFROM; 315 + perm = RAWIP_SOCKET__RECVFROM; 317 316 } 318 317 319 - rc = avc_has_perm(sksec->sid, 320 - netlbl_sid, 321 - sksec->sclass, 322 - recv_perm, 323 - ad); 318 + rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad); 324 319 if (rc == 0) 325 320 return 0; 326 321 327 - netlbl_skbuff_err(skb, rc); 322 + if (nlbl_sid != SECINITSID_UNLABELED) 323 + netlbl_skbuff_err(skb, rc); 328 324 return rc; 329 325 } 330 326
+259 -10
security/selinux/selinuxfs.c
··· 67 67 static int bool_num = 0; 68 68 static int *bool_pending_values = NULL; 69 69 70 + /* global data for classes */ 71 + static struct dentry *class_dir = NULL; 72 + static unsigned long last_class_ino; 73 + 70 74 extern void selnl_notify_setenforce(int val); 71 75 72 76 /* Check whether a task is allowed to use a security operation. */ ··· 110 106 111 107 #define SEL_INITCON_INO_OFFSET 0x01000000 112 108 #define SEL_BOOL_INO_OFFSET 0x02000000 109 + #define SEL_CLASS_INO_OFFSET 0x04000000 113 110 #define SEL_INO_MASK 0x00ffffff 114 111 115 112 #define TMPBUFLEN 12 ··· 242 237 243 238 /* declaration for sel_write_load */ 244 239 static int sel_make_bools(void); 240 + static int sel_make_classes(void); 241 + 242 + /* declaration for sel_make_class_dirs */ 243 + static int sel_make_dir(struct inode *dir, struct dentry *dentry, 244 + unsigned long *ino); 245 245 246 246 static ssize_t sel_read_mls(struct file *filp, char __user *buf, 247 247 size_t count, loff_t *ppos) ··· 297 287 goto out; 298 288 299 289 ret = sel_make_bools(); 290 + if (ret) { 291 + length = ret; 292 + goto out1; 293 + } 294 + 295 + ret = sel_make_classes(); 300 296 if (ret) 301 297 length = ret; 302 298 else 303 299 length = count; 300 + 301 + out1: 304 302 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, 305 303 "policy loaded auid=%u", 306 304 audit_get_loginuid(current->audit_context)); ··· 958 940 .write = sel_commit_bools_write, 959 941 }; 960 942 961 - /* delete booleans - partial revoke() from 962 - * fs/proc/generic.c proc_kill_inodes */ 963 - static void sel_remove_bools(struct dentry *de) 943 + /* partial revoke() from fs/proc/generic.c proc_kill_inodes */ 944 + static void sel_remove_entries(struct dentry *de) 964 945 { 965 946 struct list_head *p, *node; 966 947 struct super_block *sb = de->d_sb; ··· 1015 998 kfree(bool_pending_values); 1016 999 bool_pending_values = NULL; 1017 1000 1018 - sel_remove_bools(dir); 1001 + sel_remove_entries(dir); 1019 1002 1020 1003 if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) 1021 1004 return -ENOMEM; ··· 1065 1048 return ret; 1066 1049 err: 1067 1050 kfree(values); 1068 - sel_remove_bools(dir); 1051 + sel_remove_entries(dir); 1069 1052 ret = -ENOMEM; 1070 1053 goto out; 1071 1054 } ··· 1311 1294 return ret; 1312 1295 } 1313 1296 1314 - static int sel_make_dir(struct inode *dir, struct dentry *dentry) 1297 + static inline unsigned int sel_div(unsigned long a, unsigned long b) 1298 + { 1299 + return a / b - (a % b < 0); 1300 + } 1301 + 1302 + static inline unsigned long sel_class_to_ino(u16 class) 1303 + { 1304 + return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET; 1305 + } 1306 + 1307 + static inline u16 sel_ino_to_class(unsigned long ino) 1308 + { 1309 + return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1); 1310 + } 1311 + 1312 + static inline unsigned long sel_perm_to_ino(u16 class, u32 perm) 1313 + { 1314 + return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET; 1315 + } 1316 + 1317 + static inline u32 sel_ino_to_perm(unsigned long ino) 1318 + { 1319 + return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1); 1320 + } 1321 + 1322 + static ssize_t sel_read_class(struct file * file, char __user *buf, 1323 + size_t count, loff_t *ppos) 1324 + { 1325 + ssize_t rc, len; 1326 + char *page; 1327 + unsigned long ino = file->f_path.dentry->d_inode->i_ino; 1328 + 1329 + page = (char *)__get_free_page(GFP_KERNEL); 1330 + if (!page) { 1331 + rc = -ENOMEM; 1332 + goto out; 1333 + } 1334 + 1335 + len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino)); 1336 + rc = simple_read_from_buffer(buf, count, ppos, page, len); 1337 + free_page((unsigned long)page); 1338 + out: 1339 + return rc; 1340 + } 1341 + 1342 + static const struct file_operations sel_class_ops = { 1343 + .read = sel_read_class, 1344 + }; 1345 + 1346 + static ssize_t sel_read_perm(struct file * file, char __user *buf, 1347 + size_t count, loff_t *ppos) 1348 + { 1349 + ssize_t rc, len; 1350 + char *page; 1351 + unsigned long ino = file->f_path.dentry->d_inode->i_ino; 1352 + 1353 + page = (char *)__get_free_page(GFP_KERNEL); 1354 + if (!page) { 1355 + rc = -ENOMEM; 1356 + goto out; 1357 + } 1358 + 1359 + len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino)); 1360 + rc = simple_read_from_buffer(buf, count, ppos, page, len); 1361 + free_page((unsigned long)page); 1362 + out: 1363 + return rc; 1364 + } 1365 + 1366 + static const struct file_operations sel_perm_ops = { 1367 + .read = sel_read_perm, 1368 + }; 1369 + 1370 + static int sel_make_perm_files(char *objclass, int classvalue, 1371 + struct dentry *dir) 1372 + { 1373 + int i, rc = 0, nperms; 1374 + char **perms; 1375 + 1376 + rc = security_get_permissions(objclass, &perms, &nperms); 1377 + if (rc) 1378 + goto out; 1379 + 1380 + for (i = 0; i < nperms; i++) { 1381 + struct inode *inode; 1382 + struct dentry *dentry; 1383 + 1384 + dentry = d_alloc_name(dir, perms[i]); 1385 + if (!dentry) { 1386 + rc = -ENOMEM; 1387 + goto out1; 1388 + } 1389 + 1390 + inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); 1391 + if (!inode) { 1392 + rc = -ENOMEM; 1393 + goto out1; 1394 + } 1395 + inode->i_fop = &sel_perm_ops; 1396 + /* i+1 since perm values are 1-indexed */ 1397 + inode->i_ino = sel_perm_to_ino(classvalue, i+1); 1398 + d_add(dentry, inode); 1399 + } 1400 + 1401 + out1: 1402 + for (i = 0; i < nperms; i++) 1403 + kfree(perms[i]); 1404 + kfree(perms); 1405 + out: 1406 + return rc; 1407 + } 1408 + 1409 + static int sel_make_class_dir_entries(char *classname, int index, 1410 + struct dentry *dir) 1411 + { 1412 + struct dentry *dentry = NULL; 1413 + struct inode *inode = NULL; 1414 + int rc; 1415 + 1416 + dentry = d_alloc_name(dir, "index"); 1417 + if (!dentry) { 1418 + rc = -ENOMEM; 1419 + goto out; 1420 + } 1421 + 1422 + inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO); 1423 + if (!inode) { 1424 + rc = -ENOMEM; 1425 + goto out; 1426 + } 1427 + 1428 + inode->i_fop = &sel_class_ops; 1429 + inode->i_ino = sel_class_to_ino(index); 1430 + d_add(dentry, inode); 1431 + 1432 + dentry = d_alloc_name(dir, "perms"); 1433 + if (!dentry) { 1434 + rc = -ENOMEM; 1435 + goto out; 1436 + } 1437 + 1438 + rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino); 1439 + if (rc) 1440 + goto out; 1441 + 1442 + rc = sel_make_perm_files(classname, index, dentry); 1443 + 1444 + out: 1445 + return rc; 1446 + } 1447 + 1448 + static void sel_remove_classes(void) 1449 + { 1450 + struct list_head *class_node; 1451 + 1452 + list_for_each(class_node, &class_dir->d_subdirs) { 1453 + struct dentry *class_subdir = list_entry(class_node, 1454 + struct dentry, d_u.d_child); 1455 + struct list_head *class_subdir_node; 1456 + 1457 + list_for_each(class_subdir_node, &class_subdir->d_subdirs) { 1458 + struct dentry *d = list_entry(class_subdir_node, 1459 + struct dentry, d_u.d_child); 1460 + 1461 + if (d->d_inode) 1462 + if (d->d_inode->i_mode & S_IFDIR) 1463 + sel_remove_entries(d); 1464 + } 1465 + 1466 + sel_remove_entries(class_subdir); 1467 + } 1468 + 1469 + sel_remove_entries(class_dir); 1470 + } 1471 + 1472 + static int sel_make_classes(void) 1473 + { 1474 + int rc = 0, nclasses, i; 1475 + char **classes; 1476 + 1477 + /* delete any existing entries */ 1478 + sel_remove_classes(); 1479 + 1480 + rc = security_get_classes(&classes, &nclasses); 1481 + if (rc < 0) 1482 + goto out; 1483 + 1484 + /* +2 since classes are 1-indexed */ 1485 + last_class_ino = sel_class_to_ino(nclasses+2); 1486 + 1487 + for (i = 0; i < nclasses; i++) { 1488 + struct dentry *class_name_dir; 1489 + 1490 + class_name_dir = d_alloc_name(class_dir, classes[i]); 1491 + if (!class_name_dir) { 1492 + rc = -ENOMEM; 1493 + goto out1; 1494 + } 1495 + 1496 + rc = sel_make_dir(class_dir->d_inode, class_name_dir, 1497 + &last_class_ino); 1498 + if (rc) 1499 + goto out1; 1500 + 1501 + /* i+1 since class values are 1-indexed */ 1502 + rc = sel_make_class_dir_entries(classes[i], i+1, 1503 + class_name_dir); 1504 + if (rc) 1505 + goto out1; 1506 + } 1507 + 1508 + out1: 1509 + for (i = 0; i < nclasses; i++) 1510 + kfree(classes[i]); 1511 + kfree(classes); 1512 + out: 1513 + return rc; 1514 + } 1515 + 1516 + static int sel_make_dir(struct inode *dir, struct dentry *dentry, 1517 + unsigned long *ino) 1315 1518 { 1316 1519 int ret = 0; 1317 1520 struct inode *inode; ··· 1543 1306 } 1544 1307 inode->i_op = &simple_dir_inode_operations; 1545 1308 inode->i_fop = &simple_dir_operations; 1546 - inode->i_ino = ++sel_last_ino; 1309 + inode->i_ino = ++(*ino); 1547 1310 /* directory inodes start off with i_nlink == 2 (for "." entry) */ 1548 1311 inc_nlink(inode); 1549 1312 d_add(dentry, inode); ··· 1589 1352 goto err; 1590 1353 } 1591 1354 1592 - ret = sel_make_dir(root_inode, dentry); 1355 + ret = sel_make_dir(root_inode, dentry, &sel_last_ino); 1593 1356 if (ret) 1594 1357 goto err; 1595 1358 ··· 1622 1385 goto err; 1623 1386 } 1624 1387 1625 - ret = sel_make_dir(root_inode, dentry); 1388 + ret = sel_make_dir(root_inode, dentry, &sel_last_ino); 1626 1389 if (ret) 1627 1390 goto err; 1628 1391 ··· 1636 1399 goto err; 1637 1400 } 1638 1401 1639 - ret = sel_make_dir(root_inode, dentry); 1402 + ret = sel_make_dir(root_inode, dentry, &sel_last_ino); 1640 1403 if (ret) 1641 1404 goto err; 1642 1405 1643 1406 ret = sel_make_initcon_files(dentry); 1644 1407 if (ret) 1645 1408 goto err; 1409 + 1410 + dentry = d_alloc_name(sb->s_root, "class"); 1411 + if (!dentry) { 1412 + ret = -ENOMEM; 1413 + goto err; 1414 + } 1415 + 1416 + ret = sel_make_dir(root_inode, dentry, &sel_last_ino); 1417 + if (ret) 1418 + goto err; 1419 + 1420 + class_dir = dentry; 1646 1421 1647 1422 out: 1648 1423 return ret;
+7
security/selinux/ss/policydb.c
··· 21 21 */ 22 22 23 23 #include <linux/kernel.h> 24 + #include <linux/sched.h> 24 25 #include <linux/slab.h> 25 26 #include <linux/string.h> 26 27 #include <linux/errno.h> ··· 599 598 struct range_trans *rt, *lrt = NULL; 600 599 601 600 for (i = 0; i < SYM_NUM; i++) { 601 + cond_resched(); 602 602 hashtab_map(p->symtab[i].table, destroy_f[i], NULL); 603 603 hashtab_destroy(p->symtab[i].table); 604 604 } ··· 614 612 avtab_destroy(&p->te_avtab); 615 613 616 614 for (i = 0; i < OCON_NUM; i++) { 615 + cond_resched(); 617 616 c = p->ocontexts[i]; 618 617 while (c) { 619 618 ctmp = c; ··· 626 623 627 624 g = p->genfs; 628 625 while (g) { 626 + cond_resched(); 629 627 kfree(g->fstype); 630 628 c = g->head; 631 629 while (c) { ··· 643 639 cond_policydb_destroy(p); 644 640 645 641 for (tr = p->role_tr; tr; tr = tr->next) { 642 + cond_resched(); 646 643 kfree(ltr); 647 644 ltr = tr; 648 645 } 649 646 kfree(ltr); 650 647 651 648 for (ra = p->role_allow; ra; ra = ra -> next) { 649 + cond_resched(); 652 650 kfree(lra); 653 651 lra = ra; 654 652 } 655 653 kfree(lra); 656 654 657 655 for (rt = p->range_tr; rt; rt = rt -> next) { 656 + cond_resched(); 658 657 if (lrt) { 659 658 ebitmap_destroy(&lrt->target_range.level[0].cat); 660 659 ebitmap_destroy(&lrt->target_range.level[1].cat);
+125 -19
security/selinux/ss/services.c
··· 1587 1587 u32 *nel) 1588 1588 { 1589 1589 struct context *fromcon, usercon; 1590 - u32 *mysids, *mysids2, sid; 1590 + u32 *mysids = NULL, *mysids2, sid; 1591 1591 u32 mynel = 0, maxnel = SIDS_NEL; 1592 1592 struct user_datum *user; 1593 1593 struct role_datum *role; 1594 - struct av_decision avd; 1595 1594 struct ebitmap_node *rnode, *tnode; 1596 1595 int rc = 0, i, j; 1597 1596 1598 - if (!ss_initialized) { 1599 - *sids = NULL; 1600 - *nel = 0; 1597 + *sids = NULL; 1598 + *nel = 0; 1599 + 1600 + if (!ss_initialized) 1601 1601 goto out; 1602 - } 1603 1602 1604 1603 POLICY_RDLOCK; 1605 1604 ··· 1634 1635 if (mls_setup_user_range(fromcon, user, &usercon)) 1635 1636 continue; 1636 1637 1637 - rc = context_struct_compute_av(fromcon, &usercon, 1638 - SECCLASS_PROCESS, 1639 - PROCESS__TRANSITION, 1640 - &avd); 1641 - if (rc || !(avd.allowed & PROCESS__TRANSITION)) 1642 - continue; 1643 1638 rc = sidtab_context_to_sid(&sidtab, &usercon, &sid); 1644 - if (rc) { 1645 - kfree(mysids); 1639 + if (rc) 1646 1640 goto out_unlock; 1647 - } 1648 1641 if (mynel < maxnel) { 1649 1642 mysids[mynel++] = sid; 1650 1643 } else { ··· 1644 1653 mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC); 1645 1654 if (!mysids2) { 1646 1655 rc = -ENOMEM; 1647 - kfree(mysids); 1648 1656 goto out_unlock; 1649 1657 } 1650 1658 memcpy(mysids2, mysids, mynel * sizeof(*mysids2)); ··· 1654 1664 } 1655 1665 } 1656 1666 1657 - *sids = mysids; 1658 - *nel = mynel; 1659 - 1660 1667 out_unlock: 1661 1668 POLICY_RDUNLOCK; 1669 + if (rc || !mynel) { 1670 + kfree(mysids); 1671 + goto out; 1672 + } 1673 + 1674 + mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL); 1675 + if (!mysids2) { 1676 + rc = -ENOMEM; 1677 + kfree(mysids); 1678 + goto out; 1679 + } 1680 + for (i = 0, j = 0; i < mynel; i++) { 1681 + rc = avc_has_perm_noaudit(fromsid, mysids[i], 1682 + SECCLASS_PROCESS, 1683 + PROCESS__TRANSITION, AVC_STRICT, 1684 + NULL); 1685 + if (!rc) 1686 + mysids2[j++] = mysids[i]; 1687 + cond_resched(); 1688 + } 1689 + rc = 0; 1690 + kfree(mysids); 1691 + *sids = mysids2; 1692 + *nel = j; 1662 1693 out: 1663 1694 return rc; 1664 1695 } ··· 2004 1993 POLICY_RDUNLOCK; 2005 1994 context_destroy(&newcon); 2006 1995 out: 1996 + return rc; 1997 + } 1998 + 1999 + static int get_classes_callback(void *k, void *d, void *args) 2000 + { 2001 + struct class_datum *datum = d; 2002 + char *name = k, **classes = args; 2003 + int value = datum->value - 1; 2004 + 2005 + classes[value] = kstrdup(name, GFP_ATOMIC); 2006 + if (!classes[value]) 2007 + return -ENOMEM; 2008 + 2009 + return 0; 2010 + } 2011 + 2012 + int security_get_classes(char ***classes, int *nclasses) 2013 + { 2014 + int rc = -ENOMEM; 2015 + 2016 + POLICY_RDLOCK; 2017 + 2018 + *nclasses = policydb.p_classes.nprim; 2019 + *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); 2020 + if (!*classes) 2021 + goto out; 2022 + 2023 + rc = hashtab_map(policydb.p_classes.table, get_classes_callback, 2024 + *classes); 2025 + if (rc < 0) { 2026 + int i; 2027 + for (i = 0; i < *nclasses; i++) 2028 + kfree((*classes)[i]); 2029 + kfree(*classes); 2030 + } 2031 + 2032 + out: 2033 + POLICY_RDUNLOCK; 2034 + return rc; 2035 + } 2036 + 2037 + static int get_permissions_callback(void *k, void *d, void *args) 2038 + { 2039 + struct perm_datum *datum = d; 2040 + char *name = k, **perms = args; 2041 + int value = datum->value - 1; 2042 + 2043 + perms[value] = kstrdup(name, GFP_ATOMIC); 2044 + if (!perms[value]) 2045 + return -ENOMEM; 2046 + 2047 + return 0; 2048 + } 2049 + 2050 + int security_get_permissions(char *class, char ***perms, int *nperms) 2051 + { 2052 + int rc = -ENOMEM, i; 2053 + struct class_datum *match; 2054 + 2055 + POLICY_RDLOCK; 2056 + 2057 + match = hashtab_search(policydb.p_classes.table, class); 2058 + if (!match) { 2059 + printk(KERN_ERR "%s: unrecognized class %s\n", 2060 + __FUNCTION__, class); 2061 + rc = -EINVAL; 2062 + goto out; 2063 + } 2064 + 2065 + *nperms = match->permissions.nprim; 2066 + *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); 2067 + if (!*perms) 2068 + goto out; 2069 + 2070 + if (match->comdatum) { 2071 + rc = hashtab_map(match->comdatum->permissions.table, 2072 + get_permissions_callback, *perms); 2073 + if (rc < 0) 2074 + goto err; 2075 + } 2076 + 2077 + rc = hashtab_map(match->permissions.table, get_permissions_callback, 2078 + *perms); 2079 + if (rc < 0) 2080 + goto err; 2081 + 2082 + out: 2083 + POLICY_RDUNLOCK; 2084 + return rc; 2085 + 2086 + err: 2087 + POLICY_RDUNLOCK; 2088 + for (i = 0; i < *nperms; i++) 2089 + kfree((*perms)[i]); 2090 + kfree(*perms); 2007 2091 return rc; 2008 2092 } 2009 2093