Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
3e5f206c
Commit
3e5f206c
authored
Aug 15, 2015
by
James Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'next' of
git://git.infradead.org/users/pcmoore/selinux
into next
parents
0e38c358
fda4d578
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
915 additions
and
110 deletions
+915
-110
include/linux/lsm_audit.h
include/linux/lsm_audit.h
+7
-0
scripts/selinux/mdp/mdp.c
scripts/selinux/mdp/mdp.c
+1
-0
security/lsm_audit.c
security/lsm_audit.c
+15
-0
security/selinux/avc.c
security/selinux/avc.c
+402
-16
security/selinux/hooks.c
security/selinux/hooks.c
+97
-50
security/selinux/include/avc.h
security/selinux/include/avc.h
+6
-0
security/selinux/include/security.h
security/selinux/include/security.h
+30
-2
security/selinux/ss/avtab.c
security/selinux/ss/avtab.c
+90
-14
security/selinux/ss/avtab.h
security/selinux/ss/avtab.h
+32
-1
security/selinux/ss/conditional.c
security/selinux/ss/conditional.c
+27
-5
security/selinux/ss/conditional.h
security/selinux/ss/conditional.h
+4
-2
security/selinux/ss/policydb.c
security/selinux/ss/policydb.c
+5
-0
security/selinux/ss/services.c
security/selinux/ss/services.c
+193
-20
security/selinux/ss/services.h
security/selinux/ss/services.h
+6
-0
No files found.
include/linux/lsm_audit.h
View file @
3e5f206c
...
...
@@ -40,6 +40,11 @@ struct lsm_network_audit {
}
fam
;
};
struct
lsm_ioctlop_audit
{
struct
path
path
;
u16
cmd
;
};
/* Auxiliary data to use in generating the audit record. */
struct
common_audit_data
{
char
type
;
...
...
@@ -53,6 +58,7 @@ struct common_audit_data {
#define LSM_AUDIT_DATA_KMOD 8
#define LSM_AUDIT_DATA_INODE 9
#define LSM_AUDIT_DATA_DENTRY 10
#define LSM_AUDIT_DATA_IOCTL_OP 11
union
{
struct
path
path
;
struct
dentry
*
dentry
;
...
...
@@ -68,6 +74,7 @@ struct common_audit_data {
}
key_struct
;
#endif
char
*
kmod_name
;
struct
lsm_ioctlop_audit
*
op
;
}
u
;
/* this union contains LSM specific data */
union
{
...
...
scripts/selinux/mdp/mdp.c
View file @
3e5f206c
...
...
@@ -98,6 +98,7 @@ int main(int argc, char *argv[])
/* types, roles, and allows */
fprintf
(
fout
,
"type base_t;
\n
"
);
fprintf
(
fout
,
"role base_r;
\n
"
);
fprintf
(
fout
,
"role base_r types { base_t };
\n
"
);
for
(
i
=
0
;
secclass_map
[
i
].
name
;
i
++
)
fprintf
(
fout
,
"allow base_t base_t:%s *;
\n
"
,
...
...
security/lsm_audit.c
View file @
3e5f206c
...
...
@@ -245,6 +245,21 @@ static void dump_common_audit_data(struct audit_buffer *ab,
}
break
;
}
case
LSM_AUDIT_DATA_IOCTL_OP
:
{
struct
inode
*
inode
;
audit_log_d_path
(
ab
,
" path="
,
&
a
->
u
.
op
->
path
);
inode
=
a
->
u
.
op
->
path
.
dentry
->
d_inode
;
if
(
inode
)
{
audit_log_format
(
ab
,
" dev="
);
audit_log_untrustedstring
(
ab
,
inode
->
i_sb
->
s_id
);
audit_log_format
(
ab
,
" ino=%lu"
,
inode
->
i_ino
);
}
audit_log_format
(
ab
,
" ioctlcmd=%hx"
,
a
->
u
.
op
->
cmd
);
break
;
}
case
LSM_AUDIT_DATA_DENTRY
:
{
struct
inode
*
inode
;
...
...
security/selinux/avc.c
View file @
3e5f206c
This diff is collapsed.
Click to expand it.
security/selinux/hooks.c
View file @
3e5f206c
...
...
@@ -254,10 +254,21 @@ static void inode_free_security(struct inode *inode)
struct
inode_security_struct
*
isec
=
inode
->
i_security
;
struct
superblock_security_struct
*
sbsec
=
inode
->
i_sb
->
s_security
;
spin_lock
(
&
sbsec
->
isec_lock
);
if
(
!
list_empty
(
&
isec
->
list
))
/*
* As not all inode security structures are in a list, we check for
* empty list outside of the lock to make sure that we won't waste
* time taking a lock doing nothing.
*
* The list_del_init() function can be safely called more than once.
* It should not be possible for this function to be called with
* concurrent list_add(), but for better safety against future changes
* in the code, we use list_empty_careful() here.
*/
if
(
!
list_empty_careful
(
&
isec
->
list
))
{
spin_lock
(
&
sbsec
->
isec_lock
);
list_del_init
(
&
isec
->
list
);
spin_unlock
(
&
sbsec
->
isec_lock
);
spin_unlock
(
&
sbsec
->
isec_lock
);
}
/*
* The inode may still be referenced in a path walk and
...
...
@@ -1698,6 +1709,32 @@ static int file_has_perm(const struct cred *cred,
return
rc
;
}
/*
* Determine the label for an inode that might be unioned.
*/
static
int
selinux_determine_inode_label
(
const
struct
inode
*
dir
,
const
struct
qstr
*
name
,
u16
tclass
,
u32
*
_new_isid
)
{
const
struct
superblock_security_struct
*
sbsec
=
dir
->
i_sb
->
s_security
;
const
struct
inode_security_struct
*
dsec
=
dir
->
i_security
;
const
struct
task_security_struct
*
tsec
=
current_security
();
if
((
sbsec
->
flags
&
SE_SBINITIALIZED
)
&&
(
sbsec
->
behavior
==
SECURITY_FS_USE_MNTPOINT
))
{
*
_new_isid
=
sbsec
->
mntpoint_sid
;
}
else
if
((
sbsec
->
flags
&
SBLABEL_MNT
)
&&
tsec
->
create_sid
)
{
*
_new_isid
=
tsec
->
create_sid
;
}
else
{
return
security_transition_sid
(
tsec
->
sid
,
dsec
->
sid
,
tclass
,
name
,
_new_isid
);
}
return
0
;
}
/* Check whether a task can create a file. */
static
int
may_create
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
...
...
@@ -1714,7 +1751,6 @@ static int may_create(struct inode *dir,
sbsec
=
dir
->
i_sb
->
s_security
;
sid
=
tsec
->
sid
;
newsid
=
tsec
->
create_sid
;
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
...
...
@@ -1725,12 +1761,10 @@ static int may_create(struct inode *dir,
if
(
rc
)
return
rc
;
if
(
!
newsid
||
!
(
sbsec
->
flags
&
SBLABEL_MNT
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
tclass
,
&
dentry
->
d_name
,
&
newsid
);
if
(
rc
)
return
rc
;
}
rc
=
selinux_determine_inode_label
(
dir
,
&
dentry
->
d_name
,
tclass
,
&
newsid
);
if
(
rc
)
return
rc
;
rc
=
avc_has_perm
(
sid
,
newsid
,
tclass
,
FILE__CREATE
,
&
ad
);
if
(
rc
)
...
...
@@ -2704,32 +2738,14 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
struct
qstr
*
name
,
void
**
ctx
,
u32
*
ctxlen
)
{
const
struct
cred
*
cred
=
current_cred
();
struct
task_security_struct
*
tsec
;
struct
inode_security_struct
*
dsec
;
struct
superblock_security_struct
*
sbsec
;
struct
inode
*
dir
=
d_backing_inode
(
dentry
->
d_parent
);
u32
newsid
;
int
rc
;
tsec
=
cred
->
security
;
dsec
=
dir
->
i_security
;
sbsec
=
dir
->
i_sb
->
s_security
;
if
(
tsec
->
create_sid
&&
sbsec
->
behavior
!=
SECURITY_FS_USE_MNTPOINT
)
{
newsid
=
tsec
->
create_sid
;
}
else
{
rc
=
security_transition_sid
(
tsec
->
sid
,
dsec
->
sid
,
inode_mode_to_security_class
(
mode
),
name
,
&
newsid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"%s: security_transition_sid failed, rc=%d
\n
"
,
__func__
,
-
rc
);
return
rc
;
}
}
rc
=
selinux_determine_inode_label
(
d_inode
(
dentry
->
d_parent
),
name
,
inode_mode_to_security_class
(
mode
),
&
newsid
);
if
(
rc
)
return
rc
;
return
security_sid_to_context
(
newsid
,
(
char
**
)
ctx
,
ctxlen
);
}
...
...
@@ -2752,22 +2768,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
sid
=
tsec
->
sid
;
newsid
=
tsec
->
create_sid
;
if
((
sbsec
->
flags
&
SE_SBINITIALIZED
)
&&
(
sbsec
->
behavior
==
SECURITY_FS_USE_MNTPOINT
))
newsid
=
sbsec
->
mntpoint_sid
;
else
if
(
!
newsid
||
!
(
sbsec
->
flags
&
SBLABEL_MNT
))
{
rc
=
security_transition_sid
(
sid
,
dsec
->
sid
,
inode_mode_to_security_class
(
inode
->
i_mode
),
qstr
,
&
newsid
);
if
(
rc
)
{
printk
(
KERN_WARNING
"%s: "
"security_transition_sid failed, rc=%d (dev=%s "
"ino=%ld)
\n
"
,
__func__
,
-
rc
,
inode
->
i_sb
->
s_id
,
inode
->
i_ino
);
return
rc
;
}
}
rc
=
selinux_determine_inode_label
(
dir
,
qstr
,
inode_mode_to_security_class
(
inode
->
i_mode
),
&
newsid
);
if
(
rc
)
return
rc
;
/* Possibly defer initialization to selinux_complete_init. */
if
(
sbsec
->
flags
&
SE_SBINITIALIZED
)
{
...
...
@@ -3228,6 +3234,46 @@ static void selinux_file_free_security(struct file *file)
file_free_security
(
file
);
}
/*
* Check whether a task has the ioctl permission and cmd
* operation to an inode.
*/
int
ioctl_has_perm
(
const
struct
cred
*
cred
,
struct
file
*
file
,
u32
requested
,
u16
cmd
)
{
struct
common_audit_data
ad
;
struct
file_security_struct
*
fsec
=
file
->
f_security
;
struct
inode
*
inode
=
file_inode
(
file
);
struct
inode_security_struct
*
isec
=
inode
->
i_security
;
struct
lsm_ioctlop_audit
ioctl
;
u32
ssid
=
cred_sid
(
cred
);
int
rc
;
u8
driver
=
cmd
>>
8
;
u8
xperm
=
cmd
&
0xff
;
ad
.
type
=
LSM_AUDIT_DATA_IOCTL_OP
;
ad
.
u
.
op
=
&
ioctl
;
ad
.
u
.
op
->
cmd
=
cmd
;
ad
.
u
.
op
->
path
=
file
->
f_path
;
if
(
ssid
!=
fsec
->
sid
)
{
rc
=
avc_has_perm
(
ssid
,
fsec
->
sid
,
SECCLASS_FD
,
FD__USE
,
&
ad
);
if
(
rc
)
goto
out
;
}
if
(
unlikely
(
IS_PRIVATE
(
inode
)))
return
0
;
rc
=
avc_has_extended_perms
(
ssid
,
isec
->
sid
,
isec
->
sclass
,
requested
,
driver
,
xperm
,
&
ad
);
out:
return
rc
;
}
static
int
selinux_file_ioctl
(
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
...
...
@@ -3270,7 +3316,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
* to the file's ioctl() function.
*/
default:
error
=
file_has_perm
(
cred
,
file
,
FILE__IOCTL
);
error
=
ioctl_has_perm
(
cred
,
file
,
FILE__IOCTL
,
(
u16
)
cmd
);
}
return
error
;
}
...
...
@@ -4520,6 +4566,7 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
sksec
->
peer_sid
=
SECINITSID_UNLABELED
;
sksec
->
sid
=
SECINITSID_UNLABELED
;
sksec
->
sclass
=
SECCLASS_SOCKET
;
selinux_netlbl_sk_security_reset
(
sksec
);
sk
->
sk_security
=
sksec
;
...
...
security/selinux/include/avc.h
View file @
3e5f206c
...
...
@@ -143,6 +143,7 @@ static inline int avc_audit(u32 ssid, u32 tsid,
}
#define AVC_STRICT 1
/* Ignore permissive mode. */
#define AVC_EXTENDED_PERMS 2
/* update extended permissions */
int
avc_has_perm_noaudit
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
unsigned
flags
,
...
...
@@ -156,6 +157,10 @@ int avc_has_perm_flags(u32 ssid, u32 tsid,
struct
common_audit_data
*
auditdata
,
int
flags
);
int
avc_has_extended_perms
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u32
requested
,
u8
driver
,
u8
perm
,
struct
common_audit_data
*
ad
);
u32
avc_policy_seqno
(
void
);
#define AVC_CALLBACK_GRANT 1
...
...
@@ -166,6 +171,7 @@ u32 avc_policy_seqno(void);
#define AVC_CALLBACK_AUDITALLOW_DISABLE 32
#define AVC_CALLBACK_AUDITDENY_ENABLE 64
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
#define AVC_CALLBACK_ADD_XPERMS 256
int
avc_add_callback
(
int
(
*
callback
)(
u32
event
),
u32
events
);
...
...
security/selinux/include/security.h
View file @
3e5f206c
...
...
@@ -35,13 +35,14 @@
#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_XPERMS_IOCTL 30
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_
CONSTRAINT_NAMES
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_
XPERMS_IOCTL
#endif
/* Mask for just the mount related flags */
...
...
@@ -109,11 +110,38 @@ struct av_decision {
u32
flags
;
};
#define XPERMS_ALLOWED 1
#define XPERMS_AUDITALLOW 2
#define XPERMS_DONTAUDIT 4
#define security_xperm_set(perms, x) (perms[x >> 5] |= 1 << (x & 0x1f))
#define security_xperm_test(perms, x) (1 & (perms[x >> 5] >> (x & 0x1f)))
struct
extended_perms_data
{
u32
p
[
8
];
};
struct
extended_perms_decision
{
u8
used
;
u8
driver
;
struct
extended_perms_data
*
allowed
;
struct
extended_perms_data
*
auditallow
;
struct
extended_perms_data
*
dontaudit
;
};
struct
extended_perms
{
u16
len
;
/* length associated decision chain */
struct
extended_perms_data
drivers
;
/* flag drivers that are used */
};
/* definitions of av_decision.flags */
#define AVD_FLAGS_PERMISSIVE 0x0001
void
security_compute_av
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
);
u16
tclass
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
);
void
security_compute_xperms_decision
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
u8
driver
,
struct
extended_perms_decision
*
xpermd
);
void
security_compute_av_user
(
u32
ssid
,
u32
tsid
,
u16
tclass
,
struct
av_decision
*
avd
);
...
...
security/selinux/ss/avtab.c
View file @
3e5f206c
...
...
@@ -24,6 +24,7 @@
#include "policydb.h"
static
struct
kmem_cache
*
avtab_node_cachep
;
static
struct
kmem_cache
*
avtab_xperms_cachep
;
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.
...
...
@@ -70,11 +71,24 @@ avtab_insert_node(struct avtab *h, int hvalue,
struct
avtab_key
*
key
,
struct
avtab_datum
*
datum
)
{
struct
avtab_node
*
newnode
;
struct
avtab_extended_perms
*
xperms
;
newnode
=
kmem_cache_zalloc
(
avtab_node_cachep
,
GFP_KERNEL
);
if
(
newnode
==
NULL
)
return
NULL
;
newnode
->
key
=
*
key
;
newnode
->
datum
=
*
datum
;
if
(
key
->
specified
&
AVTAB_XPERMS
)
{
xperms
=
kmem_cache_zalloc
(
avtab_xperms_cachep
,
GFP_KERNEL
);
if
(
xperms
==
NULL
)
{
kmem_cache_free
(
avtab_node_cachep
,
newnode
);
return
NULL
;
}
*
xperms
=
*
(
datum
->
u
.
xperms
);
newnode
->
datum
.
u
.
xperms
=
xperms
;
}
else
{
newnode
->
datum
.
u
.
data
=
datum
->
u
.
data
;
}
if
(
prev
)
{
newnode
->
next
=
prev
->
next
;
prev
->
next
=
newnode
;
...
...
@@ -107,8 +121,12 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
if
(
key
->
source_type
==
cur
->
key
.
source_type
&&
key
->
target_type
==
cur
->
key
.
target_type
&&
key
->
target_class
==
cur
->
key
.
target_class
&&
(
specified
&
cur
->
key
.
specified
))
(
specified
&
cur
->
key
.
specified
))
{
/* extended perms may not be unique */
if
(
specified
&
AVTAB_XPERMS
)
break
;
return
-
EEXIST
;
}
if
(
key
->
source_type
<
cur
->
key
.
source_type
)
break
;
if
(
key
->
source_type
==
cur
->
key
.
source_type
&&
...
...
@@ -271,6 +289,9 @@ void avtab_destroy(struct avtab *h)
while
(
cur
)
{
temp
=
cur
;
cur
=
cur
->
next
;
if
(
temp
->
key
.
specified
&
AVTAB_XPERMS
)
kmem_cache_free
(
avtab_xperms_cachep
,
temp
->
datum
.
u
.
xperms
);
kmem_cache_free
(
avtab_node_cachep
,
temp
);
}
}
...
...
@@ -359,7 +380,10 @@ static uint16_t spec_order[] = {
AVTAB_AUDITALLOW
,
AVTAB_TRANSITION
,
AVTAB_CHANGE
,
AVTAB_MEMBER
AVTAB_MEMBER
,
AVTAB_XPERMS_ALLOWED
,
AVTAB_XPERMS_AUDITALLOW
,
AVTAB_XPERMS_DONTAUDIT
};
int
avtab_read_item
(
struct
avtab
*
a
,
void
*
fp
,
struct
policydb
*
pol
,
...
...
@@ -369,10 +393,11 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
{
__le16
buf16
[
4
];
u16
enabled
;
__le32
buf32
[
7
];
u32
items
,
items2
,
val
,
vers
=
pol
->
policyvers
;
struct
avtab_key
key
;
struct
avtab_datum
datum
;
struct
avtab_extended_perms
xperms
;
__le32
buf32
[
ARRAY_SIZE
(
xperms
.
perms
.
p
)];
int
i
,
rc
;
unsigned
set
;
...
...
@@ -429,11 +454,15 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
printk
(
KERN_ERR
"SELinux: avtab: entry has both access vectors and types
\n
"
);
return
-
EINVAL
;
}
if
(
val
&
AVTAB_XPERMS
)
{
printk
(
KERN_ERR
"SELinux: avtab: entry has extended permissions
\n
"
);
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
spec_order
);
i
++
)
{
if
(
val
&
spec_order
[
i
])
{
key
.
specified
=
spec_order
[
i
]
|
enabled
;
datum
.
data
=
le32_to_cpu
(
buf32
[
items
++
]);
datum
.
u
.
data
=
le32_to_cpu
(
buf32
[
items
++
]);
rc
=
insertf
(
a
,
&
key
,
&
datum
,
p
);
if
(
rc
)
return
rc
;
...
...
@@ -476,14 +505,42 @@ int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
return
-
EINVAL
;
}
rc
=
next_entry
(
buf32
,
fp
,
sizeof
(
u32
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
if
((
vers
<
POLICYDB_VERSION_XPERMS_IOCTL
)
&&
(
key
.
specified
&
AVTAB_XPERMS
))
{
printk
(
KERN_ERR
"SELinux: avtab: policy version %u does not "
"support extended permissions rules and one "
"was specified
\n
"
,
vers
);
return
-
EINVAL
;
}
else
if
(
key
.
specified
&
AVTAB_XPERMS
)
{
memset
(
&
xperms
,
0
,
sizeof
(
struct
avtab_extended_perms
));
rc
=
next_entry
(
&
xperms
.
specified
,
fp
,
sizeof
(
u8
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
rc
=
next_entry
(
&
xperms
.
driver
,
fp
,
sizeof
(
u8
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
rc
=
next_entry
(
buf32
,
fp
,
sizeof
(
u32
)
*
ARRAY_SIZE
(
xperms
.
perms
.
p
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
xperms
.
perms
.
p
);
i
++
)
xperms
.
perms
.
p
[
i
]
=
le32_to_cpu
(
buf32
[
i
]);
datum
.
u
.
xperms
=
&
xperms
;
}
else
{
rc
=
next_entry
(
buf32
,
fp
,
sizeof
(
u32
));
if
(
rc
)
{
printk
(
KERN_ERR
"SELinux: avtab: truncated entry
\n
"
);
return
rc
;
}
datum
.
u
.
data
=
le32_to_cpu
(
*
buf32
);
}
datum
.
data
=
le32_to_cpu
(
*
buf32
);
if
((
key
.
specified
&
AVTAB_TYPE
)
&&
!
policydb_type_isvalid
(
pol
,
datum
.
data
))
{
!
policydb_type_isvalid
(
pol
,
datum
.
u
.
data
))
{
printk
(
KERN_ERR
"SELinux: avtab: invalid type
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -543,8 +600,9 @@ int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
int
avtab_write_item
(
struct
policydb
*
p
,
struct
avtab_node
*
cur
,
void
*
fp
)
{
__le16
buf16
[
4
];
__le32
buf32
[
1
];
__le32
buf32
[
ARRAY_SIZE
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
)
];
int
rc
;
unsigned
int
i
;
buf16
[
0
]
=
cpu_to_le16
(
cur
->
key
.
source_type
);
buf16
[
1
]
=
cpu_to_le16
(
cur
->
key
.
target_type
);
...
...
@@ -553,8 +611,22 @@ int avtab_write_item(struct policydb *p, struct avtab_node *cur, void *fp)
rc
=
put_entry
(
buf16
,
sizeof
(
u16
),
4
,
fp
);
if
(
rc
)
return
rc
;
buf32
[
0
]
=
cpu_to_le32
(
cur
->
datum
.
data
);
rc
=
put_entry
(
buf32
,
sizeof
(
u32
),
1
,
fp
);
if
(
cur
->
key
.
specified
&
AVTAB_XPERMS
)
{
rc
=
put_entry
(
&
cur
->
datum
.
u
.
xperms
->
specified
,
sizeof
(
u8
),
1
,
fp
);
if
(
rc
)
return
rc
;
rc
=
put_entry
(
&
cur
->
datum
.
u
.
xperms
->
driver
,
sizeof
(
u8
),
1
,
fp
);
if
(
rc
)
return
rc
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
);
i
++
)
buf32
[
i
]
=
cpu_to_le32
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
[
i
]);
rc
=
put_entry
(
buf32
,
sizeof
(
u32
),
ARRAY_SIZE
(
cur
->
datum
.
u
.
xperms
->
perms
.
p
),
fp
);
}
else
{
buf32
[
0
]
=
cpu_to_le32
(
cur
->
datum
.
u
.
data
);
rc
=
put_entry
(
buf32
,
sizeof
(
u32
),
1
,
fp
);
}
if
(
rc
)
return
rc
;
return
0
;
...
...
@@ -588,9 +660,13 @@ void avtab_cache_init(void)
avtab_node_cachep
=
kmem_cache_create
(
"avtab_node"
,
sizeof
(
struct
avtab_node
),
0
,
SLAB_PANIC
,
NULL
);
avtab_xperms_cachep
=
kmem_cache_create
(
"avtab_extended_perms"
,
sizeof
(
struct
avtab_extended_perms
),
0
,
SLAB_PANIC
,
NULL
);
}
void
avtab_cache_destroy
(
void
)
{
kmem_cache_destroy
(
avtab_node_cachep
);
kmem_cache_destroy
(
avtab_xperms_cachep
);
}
security/selinux/ss/avtab.h
View file @
3e5f206c
...
...
@@ -23,6 +23,7 @@
#ifndef _SS_AVTAB_H_
#define _SS_AVTAB_H_
#include "security.h"
#include <linux/flex_array.h>
struct
avtab_key
{
...
...
@@ -37,13 +38,43 @@ struct avtab_key {
#define AVTAB_MEMBER 0x0020
#define AVTAB_CHANGE 0x0040
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
/* extended permissions */
#define AVTAB_XPERMS_ALLOWED 0x0100
#define AVTAB_XPERMS_AUDITALLOW 0x0200
#define AVTAB_XPERMS_DONTAUDIT 0x0400
#define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | \
AVTAB_XPERMS_AUDITALLOW | \
AVTAB_XPERMS_DONTAUDIT)
#define AVTAB_ENABLED_OLD 0x80000000
/* reserved for used in cond_avtab */
#define AVTAB_ENABLED 0x8000
/* reserved for used in cond_avtab */
u16
specified
;
/* what field is specified */
};
/*
* For operations that require more than the 32 permissions provided by the avc
* extended permissions may be used to provide 256 bits of permissions.
*/
struct
avtab_extended_perms
{
/* These are not flags. All 256 values may be used */
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01
#define AVTAB_XPERMS_IOCTLDRIVER 0x02
/* extension of the avtab_key specified */
u8
specified
;
/* ioctl, netfilter, ... */
/*
* if 256 bits is not adequate as is often the case with ioctls, then
* multiple extended perms may be used and the driver field
* specifies which permissions are included.
*/
u8
driver
;
/* 256 bits of permissions */
struct
extended_perms_data
perms
;
};
struct
avtab_datum
{
u32
data
;
/* access vector or type value */
union
{
u32
data
;
/* access vector or type value */
struct
avtab_extended_perms
*
xperms
;
}
u
;
};
struct
avtab_node
{
...
...
security/selinux/ss/conditional.c
View file @
3e5f206c
...
...
@@ -15,6 +15,7 @@
#include "security.h"
#include "conditional.h"
#include "services.h"
/*
* cond_evaluate_expr evaluates a conditional expr
...
...
@@ -612,21 +613,39 @@ int cond_write_list(struct policydb *p, struct cond_node *list, void *fp)
return
0
;
}
void
cond_compute_xperms
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
extended_perms_decision
*
xpermd
)
{
struct
avtab_node
*
node
;
if
(
!
ctab
||
!
key
||
!
xpermd
)
return
;
for
(
node
=
avtab_search_node
(
ctab
,
key
);
node
;
node
=
avtab_search_node_next
(
node
,
key
->
specified
))
{
if
(
node
->
key
.
specified
&
AVTAB_ENABLED
)
services_compute_xperms_decision
(
xpermd
,
node
);
}
return
;
}
/* Determine whether additional permissions are granted by the conditional
* av table, and if so, add them to the result
*/
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
)
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
)
{
struct
avtab_node
*
node
;
if
(
!
ctab
||
!
key
||
!
avd
)
if
(
!
ctab
||
!
key
||
!
avd
||
!
xperms
)
return
;
for
(
node
=
avtab_search_node
(
ctab
,
key
);
node
;
node
=
avtab_search_node_next
(
node
,
key
->
specified
))
{
if
((
u16
)(
AVTAB_ALLOWED
|
AVTAB_ENABLED
)
==
(
node
->
key
.
specified
&
(
AVTAB_ALLOWED
|
AVTAB_ENABLED
)))
avd
->
allowed
|=
node
->
datum
.
data
;
avd
->
allowed
|=
node
->
datum
.
u
.
data
;
if
((
u16
)(
AVTAB_AUDITDENY
|
AVTAB_ENABLED
)
==
(
node
->
key
.
specified
&
(
AVTAB_AUDITDENY
|
AVTAB_ENABLED
)))
/* Since a '0' in an auditdeny mask represents a
...
...
@@ -634,10 +653,13 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
* the '&' operand to ensure that all '0's in the mask
* are retained (much unlike the allow and auditallow cases).
*/
avd
->
auditdeny
&=
node
->
datum
.
data
;
avd
->
auditdeny
&=
node
->
datum
.
u
.
data
;
if
((
u16
)(
AVTAB_AUDITALLOW
|
AVTAB_ENABLED
)
==
(
node
->
key
.
specified
&
(
AVTAB_AUDITALLOW
|
AVTAB_ENABLED
)))
avd
->
auditallow
|=
node
->
datum
.
data
;
avd
->
auditallow
|=
node
->
datum
.
u
.
data
;
if
((
node
->
key
.
specified
&
AVTAB_ENABLED
)
&&
(
node
->
key
.
specified
&
AVTAB_XPERMS
))
services_compute_xperms_drivers
(
xperms
,
node
);
}
return
;
}
security/selinux/ss/conditional.h
View file @
3e5f206c
...
...
@@ -73,8 +73,10 @@ int cond_read_list(struct policydb *p, void *fp);
int
cond_write_bool
(
void
*
key
,
void
*
datum
,
void
*
ptr
);
int
cond_write_list
(
struct
policydb
*
p
,
struct
cond_node
*
list
,
void
*
fp
);
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
);
void
cond_compute_av
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
av_decision
*
avd
,
struct
extended_perms
*
xperms
);
void
cond_compute_xperms
(
struct
avtab
*
ctab
,
struct
avtab_key
*
key
,
struct
extended_perms_decision
*
xpermd
);
int
evaluate_cond_node
(
struct
policydb
*
p
,
struct
cond_node
*
node
);
#endif
/* _CONDITIONAL_H_ */
security/selinux/ss/policydb.c
View file @
3e5f206c
...
...
@@ -148,6 +148,11 @@ static struct policydb_compat_info policydb_compat[] = {
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
{
.
version
=
POLICYDB_VERSION_XPERMS_IOCTL
,
.
sym_num
=
SYM_NUM
,
.
ocon_num
=
OCON_NUM
,
},
};
static
struct
policydb_compat_info
*
policydb_lookup_compat
(
int
version
)
...
...
security/selinux/ss/services.c
View file @
3e5f206c
This diff is collapsed.
Click to expand it.
security/selinux/ss/services.h
View file @
3e5f206c
...
...
@@ -11,5 +11,11 @@
extern
struct
policydb
policydb
;
void
services_compute_xperms_drivers
(
struct
extended_perms
*
xperms
,
struct
avtab_node
*
node
);
void
services_compute_xperms_decision
(
struct
extended_perms_decision
*
xpermd
,
struct
avtab_node
*
node
);
#endif
/* _SS_SERVICES_H_ */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment