selinux: match extended permissions to their base permissions

In commit d1d991efaf34 ("selinux: Add netlink xperm support") a new
extended permission was added ("nlmsg"). This was the second extended
permission implemented in selinux ("ioctl" being the first one).

Extended permissions are associated with a base permission. It was found
that, in the access vector cache (avc), the extended permission did not
keep track of its base permission. This is an issue for a domain that is
using both extended permissions (i.e., a domain calling ioctl() on a
netlink socket). In this case, the extended permissions were
overlapping.

Keep track of the base permission in the cache. A new field "base_perm"
is added to struct extended_perms_decision to make sure that the
extended permission refers to the correct policy permission. A new field
"base_perms" is added to struct extended_perms to quickly decide if
extended permissions apply.

While it is in theory possible to retrieve the base permission from the
access vector, the same base permission may not be mapped to the same
bit for each class (e.g., "nlmsg" is mapped to a different bit for
"netlink_route_socket" and "netlink_audit_socket"). Instead, use a
constant (AVC_EXT_IOCTL or AVC_EXT_NLMSG) provided by the caller.

Fixes: d1d991efaf34 ("selinux: Add netlink xperm support")
Signed-off-by: Thiébaud Weksteen <tweek@google.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by Thiébaud Weksteen and committed by Paul Moore 5e7f0efd 900f83cf

Changed files
+65 -38
security
selinux
+34 -27
security/selinux/avc.c
··· 174 * using a linked list for extended_perms_decision lookup because the list is 175 * always small. i.e. less than 5, typically 1 176 */ 177 - static struct extended_perms_decision *avc_xperms_decision_lookup(u8 driver, 178 - struct avc_xperms_node *xp_node) 179 { 180 struct avc_xperms_decision_node *xpd_node; 181 182 list_for_each_entry(xpd_node, &xp_node->xpd_head, xpd_list) { 183 - if (xpd_node->xpd.driver == driver) 184 return &xpd_node->xpd; 185 } 186 return NULL; ··· 207 } 208 209 static void avc_xperms_allow_perm(struct avc_xperms_node *xp_node, 210 - u8 driver, u8 perm) 211 { 212 struct extended_perms_decision *xpd; 213 security_xperm_set(xp_node->xp.drivers.p, driver); 214 - xpd = avc_xperms_decision_lookup(driver, xp_node); 215 if (xpd && xpd->allowed) 216 security_xperm_set(xpd->allowed->p, perm); 217 } ··· 248 static void avc_copy_xperms_decision(struct extended_perms_decision *dest, 249 struct extended_perms_decision *src) 250 { 251 dest->driver = src->driver; 252 dest->used = src->used; 253 if (dest->used & XPERMS_ALLOWED) ··· 276 */ 277 u8 i = perm >> 5; 278 279 dest->used = src->used; 280 if (dest->used & XPERMS_ALLOWED) 281 dest->allowed->p[i] = src->allowed->p[i]; ··· 362 363 memcpy(dest->xp.drivers.p, src->xp.drivers.p, sizeof(dest->xp.drivers.p)); 364 dest->xp.len = src->xp.len; 365 366 /* for each source xpd allocate a destination xpd and copy */ 367 list_for_each_entry(src_xpd, &src->xpd_head, xpd_list) { ··· 813 * @event : Updating event 814 * @perms : Permission mask bits 815 * @driver: xperm driver information 816 * @xperm: xperm permissions 817 * @ssid: AVC entry source sid 818 * @tsid: AVC entry target sid ··· 827 * otherwise, this function updates the AVC entry. The original AVC-entry object 828 * will release later by RCU. 829 */ 830 - static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid, 831 - u32 tsid, u16 tclass, u32 seqno, 832 - struct extended_perms_decision *xpd, 833 - u32 flags) 834 { 835 u32 hvalue; 836 int rc = 0; ··· 886 case AVC_CALLBACK_GRANT: 887 node->ae.avd.allowed |= perms; 888 if (node->ae.xp_node && (flags & AVC_EXTENDED_PERMS)) 889 - avc_xperms_allow_perm(node->ae.xp_node, driver, xperm); 890 break; 891 case AVC_CALLBACK_TRY_REVOKE: 892 case AVC_CALLBACK_REVOKE: ··· 993 avc_insert(ssid, tsid, tclass, avd, xp_node); 994 } 995 996 - static noinline int avc_denied(u32 ssid, u32 tsid, 997 - u16 tclass, u32 requested, 998 - u8 driver, u8 xperm, unsigned int flags, 999 - struct av_decision *avd) 1000 { 1001 if (flags & AVC_STRICT) 1002 return -EACCES; ··· 1004 !(avd->flags & AVD_FLAGS_PERMISSIVE)) 1005 return -EACCES; 1006 1007 - avc_update_node(AVC_CALLBACK_GRANT, requested, driver, 1008 xperm, ssid, tsid, tclass, avd->seqno, NULL, flags); 1009 return 0; 1010 } ··· 1017 * driver field is used to specify which set contains the permission. 1018 */ 1019 int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, 1020 - u8 driver, u8 xperm, struct common_audit_data *ad) 1021 { 1022 struct avc_node *node; 1023 struct av_decision avd; ··· 1053 local_xpd.auditallow = &auditallow; 1054 local_xpd.dontaudit = &dontaudit; 1055 1056 - xpd = avc_xperms_decision_lookup(driver, xp_node); 1057 if (unlikely(!xpd)) { 1058 /* 1059 * Compute the extended_perms_decision only if the driver 1060 - * is flagged 1061 */ 1062 - if (!security_xperm_test(xp_node->xp.drivers.p, driver)) { 1063 avd.allowed &= ~requested; 1064 goto decision; 1065 } 1066 rcu_read_unlock(); 1067 - security_compute_xperms_decision(ssid, tsid, tclass, 1068 - driver, &local_xpd); 1069 rcu_read_lock(); 1070 - avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, 1071 - driver, xperm, ssid, tsid, tclass, avd.seqno, 1072 &local_xpd, 0); 1073 } else { 1074 avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd); ··· 1082 decision: 1083 denied = requested & ~(avd.allowed); 1084 if (unlikely(denied)) 1085 - rc = avc_denied(ssid, tsid, tclass, requested, 1086 - driver, xperm, AVC_EXTENDED_PERMS, &avd); 1087 1088 rcu_read_unlock(); 1089 ··· 1117 avc_compute_av(ssid, tsid, tclass, avd, &xp_node); 1118 denied = requested & ~(avd->allowed); 1119 if (unlikely(denied)) 1120 - return avc_denied(ssid, tsid, tclass, requested, 0, 0, 1121 flags, avd); 1122 return 0; 1123 } ··· 1165 rcu_read_unlock(); 1166 1167 if (unlikely(denied)) 1168 - return avc_denied(ssid, tsid, tclass, requested, 0, 0, 1169 flags, avd); 1170 return 0; 1171 }
··· 174 * using a linked list for extended_perms_decision lookup because the list is 175 * always small. i.e. less than 5, typically 1 176 */ 177 + static struct extended_perms_decision * 178 + avc_xperms_decision_lookup(u8 driver, u8 base_perm, 179 + struct avc_xperms_node *xp_node) 180 { 181 struct avc_xperms_decision_node *xpd_node; 182 183 list_for_each_entry(xpd_node, &xp_node->xpd_head, xpd_list) { 184 + if (xpd_node->xpd.driver == driver && 185 + xpd_node->xpd.base_perm == base_perm) 186 return &xpd_node->xpd; 187 } 188 return NULL; ··· 205 } 206 207 static void avc_xperms_allow_perm(struct avc_xperms_node *xp_node, 208 + u8 driver, u8 base_perm, u8 perm) 209 { 210 struct extended_perms_decision *xpd; 211 security_xperm_set(xp_node->xp.drivers.p, driver); 212 + xp_node->xp.base_perms |= base_perm; 213 + xpd = avc_xperms_decision_lookup(driver, base_perm, xp_node); 214 if (xpd && xpd->allowed) 215 security_xperm_set(xpd->allowed->p, perm); 216 } ··· 245 static void avc_copy_xperms_decision(struct extended_perms_decision *dest, 246 struct extended_perms_decision *src) 247 { 248 + dest->base_perm = src->base_perm; 249 dest->driver = src->driver; 250 dest->used = src->used; 251 if (dest->used & XPERMS_ALLOWED) ··· 272 */ 273 u8 i = perm >> 5; 274 275 + dest->base_perm = src->base_perm; 276 dest->used = src->used; 277 if (dest->used & XPERMS_ALLOWED) 278 dest->allowed->p[i] = src->allowed->p[i]; ··· 357 358 memcpy(dest->xp.drivers.p, src->xp.drivers.p, sizeof(dest->xp.drivers.p)); 359 dest->xp.len = src->xp.len; 360 + dest->xp.base_perms = src->xp.base_perms; 361 362 /* for each source xpd allocate a destination xpd and copy */ 363 list_for_each_entry(src_xpd, &src->xpd_head, xpd_list) { ··· 807 * @event : Updating event 808 * @perms : Permission mask bits 809 * @driver: xperm driver information 810 + * @base_perm: the base permission associated with the extended permission 811 * @xperm: xperm permissions 812 * @ssid: AVC entry source sid 813 * @tsid: AVC entry target sid ··· 820 * otherwise, this function updates the AVC entry. The original AVC-entry object 821 * will release later by RCU. 822 */ 823 + static int avc_update_node(u32 event, u32 perms, u8 driver, u8 base_perm, 824 + u8 xperm, u32 ssid, u32 tsid, u16 tclass, u32 seqno, 825 + struct extended_perms_decision *xpd, u32 flags) 826 { 827 u32 hvalue; 828 int rc = 0; ··· 880 case AVC_CALLBACK_GRANT: 881 node->ae.avd.allowed |= perms; 882 if (node->ae.xp_node && (flags & AVC_EXTENDED_PERMS)) 883 + avc_xperms_allow_perm(node->ae.xp_node, driver, base_perm, xperm); 884 break; 885 case AVC_CALLBACK_TRY_REVOKE: 886 case AVC_CALLBACK_REVOKE: ··· 987 avc_insert(ssid, tsid, tclass, avd, xp_node); 988 } 989 990 + static noinline int avc_denied(u32 ssid, u32 tsid, u16 tclass, u32 requested, 991 + u8 driver, u8 base_perm, u8 xperm, 992 + unsigned int flags, struct av_decision *avd) 993 { 994 if (flags & AVC_STRICT) 995 return -EACCES; ··· 999 !(avd->flags & AVD_FLAGS_PERMISSIVE)) 1000 return -EACCES; 1001 1002 + avc_update_node(AVC_CALLBACK_GRANT, requested, driver, base_perm, 1003 xperm, ssid, tsid, tclass, avd->seqno, NULL, flags); 1004 return 0; 1005 } ··· 1012 * driver field is used to specify which set contains the permission. 1013 */ 1014 int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, 1015 + u8 driver, u8 base_perm, u8 xperm, 1016 + struct common_audit_data *ad) 1017 { 1018 struct avc_node *node; 1019 struct av_decision avd; ··· 1047 local_xpd.auditallow = &auditallow; 1048 local_xpd.dontaudit = &dontaudit; 1049 1050 + xpd = avc_xperms_decision_lookup(driver, base_perm, xp_node); 1051 if (unlikely(!xpd)) { 1052 /* 1053 * Compute the extended_perms_decision only if the driver 1054 + * is flagged and the base permission is known. 1055 */ 1056 + if (!security_xperm_test(xp_node->xp.drivers.p, driver) || 1057 + !(xp_node->xp.base_perms & base_perm)) { 1058 avd.allowed &= ~requested; 1059 goto decision; 1060 } 1061 rcu_read_unlock(); 1062 + security_compute_xperms_decision(ssid, tsid, tclass, driver, 1063 + base_perm, &local_xpd); 1064 rcu_read_lock(); 1065 + avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, driver, 1066 + base_perm, xperm, ssid, tsid, tclass, avd.seqno, 1067 &local_xpd, 0); 1068 } else { 1069 avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd); ··· 1075 decision: 1076 denied = requested & ~(avd.allowed); 1077 if (unlikely(denied)) 1078 + rc = avc_denied(ssid, tsid, tclass, requested, driver, 1079 + base_perm, xperm, AVC_EXTENDED_PERMS, &avd); 1080 1081 rcu_read_unlock(); 1082 ··· 1110 avc_compute_av(ssid, tsid, tclass, avd, &xp_node); 1111 denied = requested & ~(avd->allowed); 1112 if (unlikely(denied)) 1113 + return avc_denied(ssid, tsid, tclass, requested, 0, 0, 0, 1114 flags, avd); 1115 return 0; 1116 } ··· 1158 rcu_read_unlock(); 1159 1160 if (unlikely(denied)) 1161 + return avc_denied(ssid, tsid, tclass, requested, 0, 0, 0, 1162 flags, avd); 1163 return 0; 1164 }
+3 -3
security/selinux/hooks.c
··· 3688 return 0; 3689 3690 isec = inode_security(inode); 3691 - rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, 3692 - requested, driver, xperm, &ad); 3693 out: 3694 return rc; 3695 } ··· 5952 xperm = nlmsg_type & 0xff; 5953 5954 return avc_has_extended_perms(current_sid(), sksec->sid, sksec->sclass, 5955 - perms, driver, xperm, &ad); 5956 } 5957 5958 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
··· 3688 return 0; 3689 3690 isec = inode_security(inode); 3691 + rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, requested, 3692 + driver, AVC_EXT_IOCTL, xperm, &ad); 3693 out: 3694 return rc; 3695 } ··· 5952 xperm = nlmsg_type & 0xff; 5953 5954 return avc_has_extended_perms(current_sid(), sksec->sid, sksec->sclass, 5955 + perms, driver, AVC_EXT_NLMSG, xperm, &ad); 5956 } 5957 5958 static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
+4 -1
security/selinux/include/avc.h
··· 136 int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested, 137 struct common_audit_data *auditdata); 138 139 int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, 140 - u8 driver, u8 perm, struct common_audit_data *ad); 141 142 u32 avc_policy_seqno(void); 143
··· 136 int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested, 137 struct common_audit_data *auditdata); 138 139 + #define AVC_EXT_IOCTL (1 << 0) /* Cache entry for an ioctl extended permission */ 140 + #define AVC_EXT_NLMSG (1 << 1) /* Cache entry for an nlmsg extended permission */ 141 int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, 142 + u8 driver, u8 base_perm, u8 perm, 143 + struct common_audit_data *ad); 144 145 u32 avc_policy_seqno(void); 146
+3
security/selinux/include/security.h
··· 239 struct extended_perms_decision { 240 u8 used; 241 u8 driver; 242 struct extended_perms_data *allowed; 243 struct extended_perms_data *auditallow; 244 struct extended_perms_data *dontaudit; ··· 247 248 struct extended_perms { 249 u16 len; /* length associated decision chain */ 250 struct extended_perms_data drivers; /* flag drivers that are used */ 251 }; 252 ··· 259 struct extended_perms *xperms); 260 261 void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, u8 driver, 262 struct extended_perms_decision *xpermd); 263 264 void security_compute_av_user(u32 ssid, u32 tsid, u16 tclass,
··· 239 struct extended_perms_decision { 240 u8 used; 241 u8 driver; 242 + u8 base_perm; 243 struct extended_perms_data *allowed; 244 struct extended_perms_data *auditallow; 245 struct extended_perms_data *dontaudit; ··· 246 247 struct extended_perms { 248 u16 len; /* length associated decision chain */ 249 + u8 base_perms; /* which base permissions are covered */ 250 struct extended_perms_data drivers; /* flag drivers that are used */ 251 }; 252 ··· 257 struct extended_perms *xperms); 258 259 void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, u8 driver, 260 + u8 base_perm, 261 struct extended_perms_decision *xpermd); 262 263 void security_compute_av_user(u32 ssid, u32 tsid, u16 tclass,
+21 -7
security/selinux/ss/services.c
··· 582 } 583 584 /* 585 - * Flag which drivers have permissions. 586 */ 587 void services_compute_xperms_drivers( 588 struct extended_perms *xperms, ··· 592 593 switch (node->datum.u.xperms->specified) { 594 case AVTAB_XPERMS_IOCTLDRIVER: 595 /* if one or more driver has all permissions allowed */ 596 for (i = 0; i < ARRAY_SIZE(xperms->drivers.p); i++) 597 xperms->drivers.p[i] |= node->datum.u.xperms->perms.p[i]; 598 break; 599 case AVTAB_XPERMS_IOCTLFUNCTION: 600 case AVTAB_XPERMS_NLMSG: 601 /* if allowing permissions within a driver */ 602 security_xperm_set(xperms->drivers.p, 603 node->datum.u.xperms->driver); ··· 638 avd->auditallow = 0; 639 avd->auditdeny = 0xffffffff; 640 if (xperms) { 641 - memset(&xperms->drivers, 0, sizeof(xperms->drivers)); 642 - xperms->len = 0; 643 } 644 645 if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) { ··· 975 { 976 switch (node->datum.u.xperms->specified) { 977 case AVTAB_XPERMS_IOCTLFUNCTION: 978 - case AVTAB_XPERMS_NLMSG: 979 - if (xpermd->driver != node->datum.u.xperms->driver) 980 return; 981 break; 982 case AVTAB_XPERMS_IOCTLDRIVER: 983 - if (!security_xperm_test(node->datum.u.xperms->perms.p, 984 - xpermd->driver)) 985 return; 986 break; 987 default: ··· 1022 u32 tsid, 1023 u16 orig_tclass, 1024 u8 driver, 1025 struct extended_perms_decision *xpermd) 1026 { 1027 struct selinux_policy *policy; ··· 1036 struct ebitmap_node *snode, *tnode; 1037 unsigned int i, j; 1038 1039 xpermd->driver = driver; 1040 xpermd->used = 0; 1041 memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p));
··· 582 } 583 584 /* 585 + * Flag which drivers have permissions and which base permissions are covered. 586 */ 587 void services_compute_xperms_drivers( 588 struct extended_perms *xperms, ··· 592 593 switch (node->datum.u.xperms->specified) { 594 case AVTAB_XPERMS_IOCTLDRIVER: 595 + xperms->base_perms |= AVC_EXT_IOCTL; 596 /* if one or more driver has all permissions allowed */ 597 for (i = 0; i < ARRAY_SIZE(xperms->drivers.p); i++) 598 xperms->drivers.p[i] |= node->datum.u.xperms->perms.p[i]; 599 break; 600 case AVTAB_XPERMS_IOCTLFUNCTION: 601 + xperms->base_perms |= AVC_EXT_IOCTL; 602 + /* if allowing permissions within a driver */ 603 + security_xperm_set(xperms->drivers.p, 604 + node->datum.u.xperms->driver); 605 + break; 606 case AVTAB_XPERMS_NLMSG: 607 + xperms->base_perms |= AVC_EXT_NLMSG; 608 /* if allowing permissions within a driver */ 609 security_xperm_set(xperms->drivers.p, 610 node->datum.u.xperms->driver); ··· 631 avd->auditallow = 0; 632 avd->auditdeny = 0xffffffff; 633 if (xperms) { 634 + memset(xperms, 0, sizeof(*xperms)); 635 } 636 637 if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) { ··· 969 { 970 switch (node->datum.u.xperms->specified) { 971 case AVTAB_XPERMS_IOCTLFUNCTION: 972 + if (xpermd->base_perm != AVC_EXT_IOCTL || 973 + xpermd->driver != node->datum.u.xperms->driver) 974 return; 975 break; 976 case AVTAB_XPERMS_IOCTLDRIVER: 977 + if (xpermd->base_perm != AVC_EXT_IOCTL || 978 + !security_xperm_test(node->datum.u.xperms->perms.p, 979 + xpermd->driver)) 980 + return; 981 + break; 982 + case AVTAB_XPERMS_NLMSG: 983 + if (xpermd->base_perm != AVC_EXT_NLMSG || 984 + xpermd->driver != node->datum.u.xperms->driver) 985 return; 986 break; 987 default: ··· 1010 u32 tsid, 1011 u16 orig_tclass, 1012 u8 driver, 1013 + u8 base_perm, 1014 struct extended_perms_decision *xpermd) 1015 { 1016 struct selinux_policy *policy; ··· 1023 struct ebitmap_node *snode, *tnode; 1024 unsigned int i, j; 1025 1026 + xpermd->base_perm = base_perm; 1027 xpermd->driver = driver; 1028 xpermd->used = 0; 1029 memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p));