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

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
174174 * using a linked list for extended_perms_decision lookup because the list is
175175 * always small. i.e. less than 5, typically 1
176176 */
177−static struct extended_perms_decision *avc_xperms_decision_lookup(u8 driver,
178− struct avc_xperms_node *xp_node)
177+static struct extended_perms_decision *
178+avc_xperms_decision_lookup(u8 driver, u8 base_perm,
179+ struct avc_xperms_node *xp_node)
179180 {
180181 struct avc_xperms_decision_node *xpd_node;
181182
182183 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)
184186 return &xpd_node->xpd;
185187 }
186188 return NULL;
@@ -205,11 +207,12 @@ avc_xperms_has_perm(struct extended_perms_decision *xpd, · 18 unmodified lines
205207 }
206208
207209 static void avc_xperms_allow_perm(struct avc_xperms_node *xp_node,
208− u8 driver, u8 perm)
210+ u8 driver, u8 base_perm, u8 perm)
209211 {
210212 struct extended_perms_decision *xpd;
211213 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);
213216 if (xpd && xpd->allowed)
214217 security_xperm_set(xpd->allowed->p, perm);
215218 }
@@ -245,6 +248,7 @@ static void avc_xperms_free(struct avc_xperms_node *xp_node) · 29 unmodified lines
245248 static void avc_copy_xperms_decision(struct extended_perms_decision *dest,
246249 struct extended_perms_decision *src)
247250 {
251+ dest->base_perm = src->base_perm;
248252 dest->driver = src->driver;
249253 dest->used = src->used;
250254 if (dest->used & XPERMS_ALLOWED)
@@ -272,6 +276,7 @@ static inline void avc_quick_copy_xperms_decision(u8 perm, · 21 unmodified lines
272276 */
273277 u8 i = perm >> 5;
274278
279+ dest->base_perm = src->base_perm;
275280 dest->used = src->used;
276281 if (dest->used & XPERMS_ALLOWED)
277282 dest->allowed->p[i] = src->allowed->p[i];
@@ -357,6 +362,7 @@ static int avc_xperms_populate(struct avc_node *node, · 79 unmodified lines
357362
358363 memcpy(dest->xp.drivers.p, src->xp.drivers.p, sizeof(dest->xp.drivers.p));
359364 dest->xp.len = src->xp.len;
365+ dest->xp.base_perms = src->xp.base_perms;
360366
361367 /* for each source xpd allocate a destination xpd and copy */
362368 list_for_each_entry(src_xpd, &src->xpd_head, xpd_list) {
@@ -807,6 +813,7 @@ out: · 444 unmodified lines
807813 * @event : Updating event
808814 * @perms : Permission mask bits
809815 * @driver: xperm driver information
816+ * @base_perm: the base permission associated with the extended permission
810817 * @xperm: xperm permissions
811818 * @ssid: AVC entry source sid
812819 * @tsid: AVC entry target sid
@@ -820,10 +827,9 @@ out: · 7 unmodified lines
820827 * otherwise, this function updates the AVC entry. The original AVC-entry object
821828 * will release later by RCU.
822829 */
823−static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
824− u32 tsid, u16 tclass, u32 seqno,
825− struct extended_perms_decision *xpd,
826− u32 flags)
830+static int avc_update_node(u32 event, u32 perms, u8 driver, u8 base_perm,
831+ u8 xperm, u32 ssid, u32 tsid, u16 tclass, u32 seqno,
832+ struct extended_perms_decision *xpd, u32 flags)
827833 {
828834 u32 hvalue;
829835 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
880886 case AVC_CALLBACK_GRANT:
881887 node->ae.avd.allowed |= perms;
882888 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);
884890 break;
885891 case AVC_CALLBACK_TRY_REVOKE:
886892 case AVC_CALLBACK_REVOKE:
@@ -987,10 +993,9 @@ static noinline void avc_compute_av(u32 ssid, u32 tsid, u16 tclass, · 100 unmodified lines
987993 avc_insert(ssid, tsid, tclass, avd, xp_node);
988994 }
989995
990−static noinline int avc_denied(u32 ssid, u32 tsid,
991− u16 tclass, u32 requested,
992− u8 driver, u8 xperm, unsigned int flags,
993− struct av_decision *avd)
996+static noinline int avc_denied(u32 ssid, u32 tsid, u16 tclass, u32 requested,
997+ u8 driver, u8 base_perm, u8 xperm,
998+ unsigned int flags, struct av_decision *avd)
994999 {
9951000 if (flags & AVC_STRICT)
9961001 return -EACCES;
@@ -999,7 +1004,7 @@ static noinline int avc_denied(u32 ssid, u32 tsid, · 2 unmodified lines
9991004 !(avd->flags & AVD_FLAGS_PERMISSIVE))
10001005 return -EACCES;
10011006
1002− avc_update_node(AVC_CALLBACK_GRANT, requested, driver,
1007+ avc_update_node(AVC_CALLBACK_GRANT, requested, driver, base_perm,
10031008 xperm, ssid, tsid, tclass, avd->seqno, NULL, flags);
10041009 return 0;
10051010 }
@@ -1012,7 +1017,8 @@ static noinline int avc_denied(u32 ssid, u32 tsid, · 6 unmodified lines
10121017 * driver field is used to specify which set contains the permission.
10131018 */
10141019 int 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)
10161022 {
10171023 struct avc_node *node;
10181024 struct av_decision avd;
@@ -1047,22 +1053,23 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested, · 28 unmodified lines
10471053 local_xpd.auditallow = &auditallow;
10481054 local_xpd.dontaudit = &dontaudit;
10491055
1050− xpd = avc_xperms_decision_lookup(driver, xp_node);
1056+ xpd = avc_xperms_decision_lookup(driver, base_perm, xp_node);
10511057 if (unlikely(!xpd)) {
10521058 /*
10531059 * Compute the extended_perms_decision only if the driver
1054− * is flagged
1060+ * is flagged and the base permission is known.
10551061 */
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)) {
10571064 avd.allowed &= ~requested;
10581065 goto decision;
10591066 }
10601067 rcu_read_unlock();
1061− security_compute_xperms_decision(ssid, tsid, tclass,
1062− driver, &local_xpd);
1068+ security_compute_xperms_decision(ssid, tsid, tclass, driver,
1069+ base_perm, &local_xpd);
10631070 rcu_read_lock();
1064− avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested,
1065− driver, xperm, ssid, tsid, tclass, avd.seqno,
1071+ avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, driver,
1072+ base_perm, xperm, ssid, tsid, tclass, avd.seqno,
10661073 &local_xpd, 0);
10671074 } else {
10681075 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
10751082 decision:
10761083 denied = requested & ~(avd.allowed);
10771084 if (unlikely(denied))
1078− rc = avc_denied(ssid, tsid, tclass, requested,
1079− driver, xperm, AVC_EXTENDED_PERMS, &avd);
1085+ rc = avc_denied(ssid, tsid, tclass, requested, driver,
1086+ base_perm, xperm, AVC_EXTENDED_PERMS, &avd);
10801087
10811088 rcu_read_unlock();
10821089
@@ -1110,7 +1117,7 @@ static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass, · 27 unmodified lines
11101117 avc_compute_av(ssid, tsid, tclass, avd, &xp_node);
11111118 denied = requested & ~(avd->allowed);
11121119 if (unlikely(denied))
1113− return avc_denied(ssid, tsid, tclass, requested, 0, 0,
1120+ return avc_denied(ssid, tsid, tclass, requested, 0, 0, 0,
11141121 flags, avd);
11151122 return 0;
11161123 }
@@ -1158,7 +1165,7 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, · 41 unmodified lines
11581165 rcu_read_unlock();
11591166
11601167 if (unlikely(denied))
1161− return avc_denied(ssid, tsid, tclass, requested, 0, 0,
1168+ return avc_denied(ssid, tsid, tclass, requested, 0, 0, 0,
11621169 flags, avd);
11631170 return 0;
11641171 }
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
36883688 return 0;
36893689
36903690 isec = inode_security(inode);
3691− rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3692− requested, driver, xperm, &ad);
3691+ rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, requested,
3692+ driver, AVC_EXT_IOCTL, xperm, &ad);
36933693 out:
36943694 return rc;
36953695 }
@@ -5952,7 +5952,7 @@ static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_t · 2256 unmodified lines
59525952 xperm = nlmsg_type & 0xff;
59535953
59545954 return avc_has_extended_perms(current_sid(), sksec->sid, sksec->sclass,
5955− perms, driver, xperm, &ad);
5955+ perms, driver, AVC_EXT_NLMSG, xperm, &ad);
59565956 }
59575957
59585958 static 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
136136 int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested,
137137 struct common_audit_data *auditdata);
138138
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 */
139141 int 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);
141144
142145 u32 avc_policy_seqno(void);
143146
security/selinux/include/security.h+3−0
@@ -239,6 +239,7 @@ struct extended_perms_data { · 238 unmodified lines
239239 struct extended_perms_decision {
240240 u8 used;
241241 u8 driver;
242+ u8 base_perm;
242243 struct extended_perms_data *allowed;
243244 struct extended_perms_data *auditallow;
244245 struct extended_perms_data *dontaudit;
@@ -246,6 +247,7 @@ struct extended_perms_decision { · 1 unmodified line
246247
247248 struct extended_perms {
248249 u16 len; /* length associated decision chain */
250+ u8 base_perms; /* which base permissions are covered */
249251 struct extended_perms_data drivers; /* flag drivers that are used */
250252 };
251253
@@ -257,6 +259,7 @@ void security_compute_av(u32 ssid, u32 tsid, u16 tclass, · 5 unmodified lines
257259 struct extended_perms *xperms);
258260
259261 void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, u8 driver,
262+ u8 base_perm,
260263 struct extended_perms_decision *xpermd);
261264
262265 void 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
582582 }
583583
584584 /*
585− * Flag which drivers have permissions.
585+ * Flag which drivers have permissions and which base permissions are covered.
586586 */
587587 void services_compute_xperms_drivers(
588588 struct extended_perms *xperms,
@@ -592,12 +592,19 @@ void services_compute_xperms_drivers( · 3 unmodified lines
592592
593593 switch (node->datum.u.xperms->specified) {
594594 case AVTAB_XPERMS_IOCTLDRIVER:
595+ xperms->base_perms |= AVC_EXT_IOCTL;
595596 /* if one or more driver has all permissions allowed */
596597 for (i = 0; i < ARRAY_SIZE(xperms->drivers.p); i++)
597598 xperms->drivers.p[i] |= node->datum.u.xperms->perms.p[i];
598599 break;
599600 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;
600606 case AVTAB_XPERMS_NLMSG:
607+ xperms->base_perms |= AVC_EXT_NLMSG;
601608 /* if allowing permissions within a driver */
602609 security_xperm_set(xperms->drivers.p,
603610 node->datum.u.xperms->driver);
@@ -631,8 +638,7 @@ static void context_struct_compute_av(struct policydb *policydb, · 27 unmodified lines
631638 avd->auditallow = 0;
632639 avd->auditdeny = 0xffffffff;
633640 if (xperms) {
634− memset(&xperms->drivers, 0, sizeof(xperms->drivers));
635− xperms->len = 0;
641+ memset(xperms, 0, sizeof(*xperms));
636642 }
637643
638644 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
969975 {
970976 switch (node->datum.u.xperms->specified) {
971977 case AVTAB_XPERMS_IOCTLFUNCTION:
972− case AVTAB_XPERMS_NLMSG:
973− if (xpermd->driver != node->datum.u.xperms->driver)
978+ if (xpermd->base_perm != AVC_EXT_IOCTL ||
979+ xpermd->driver != node->datum.u.xperms->driver)
974980 return;
975981 break;
976982 case AVTAB_XPERMS_IOCTLDRIVER:
977− if (!security_xperm_test(node->datum.u.xperms->perms.p,
978− xpermd->driver))
983+ if (xpermd->base_perm != AVC_EXT_IOCTL ||
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)
979991 return;
980992 break;
981993 default:
@@ -1010,6 +1022,7 @@ void security_compute_xperms_decision(u32 ssid, · 28 unmodified lines
10101022 u32 tsid,
10111023 u16 orig_tclass,
10121024 u8 driver,
1025+ u8 base_perm,
10131026 struct extended_perms_decision *xpermd)
10141027 {
10151028 struct selinux_policy *policy;
@@ -1023,6 +1036,7 @@ void security_compute_xperms_decision(u32 ssid, · 7 unmodified lines
10231036 struct ebitmap_node *snode, *tnode;
10241037 unsigned int i, j;
10251038
1039+ xpermd->base_perm = base_perm;
10261040 xpermd->driver = driver;
10271041 xpermd->used = 0;
10281042 memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p));