History

Merge tag 'selinux-pr-20250107' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux

Pull selinux fix from Paul Moore: "A single SELinux patch to address a problem with a single domain using multiple xperm classes" * tag 'selinux-pr-20250107' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux: selinux: match extended permissions to their base permissions

Linus Torvalds committed 1 year ago

Commit 09a0fa92 parents fbfd64d 5e7f0ef5 files · +65 −38Browse files

Showing the changes to security (5 of 5 files). Show all

Unified · Split

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