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