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
a6926cc9
Commit
a6926cc9
authored
May 06, 2016
by
James Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'stable-4.7' of
git://git.infradead.org/users/pcmoore/selinux
into next
parents
0250abcd
c2316dbf
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
128 additions
and
61 deletions
+128
-61
net/netlabel/netlabel_kapi.c
net/netlabel/netlabel_kapi.c
+1
-1
security/selinux/hooks.c
security/selinux/hooks.c
+102
-42
security/selinux/include/classmap.h
security/selinux/include/classmap.h
+19
-11
security/selinux/include/conditional.h
security/selinux/include/conditional.h
+1
-1
security/selinux/include/objsec.h
security/selinux/include/objsec.h
+2
-3
security/selinux/ss/services.c
security/selinux/ss/services.c
+3
-3
No files found.
net/netlabel/netlabel_kapi.c
View file @
a6926cc9
...
...
@@ -677,7 +677,7 @@ int netlbl_catmap_setrng(struct netlbl_lsm_catmap **catmap,
u32
spot
=
start
;
while
(
rc
==
0
&&
spot
<=
end
)
{
if
(((
spot
&
(
BITS_PER_LONG
-
1
))
!
=
0
)
&&
if
(((
spot
&
(
BITS_PER_LONG
-
1
))
=
=
0
)
&&
((
end
-
spot
)
>
BITS_PER_LONG
))
{
rc
=
netlbl_catmap_setlong
(
catmap
,
spot
,
...
...
security/selinux/hooks.c
View file @
a6926cc9
...
...
@@ -259,7 +259,7 @@ static int __inode_security_revalidate(struct inode *inode,
might_sleep_if
(
may_sleep
);
if
(
isec
->
initialized
==
LABEL_INVALI
D
)
{
if
(
ss_initialized
&&
isec
->
initialized
!=
LABEL_INITIALIZE
D
)
{
if
(
!
may_sleep
)
return
-
ECHILD
;
...
...
@@ -297,6 +297,13 @@ static struct inode_security_struct *inode_security(struct inode *inode)
return
inode
->
i_security
;
}
static
struct
inode_security_struct
*
backing_inode_security_novalidate
(
struct
dentry
*
dentry
)
{
struct
inode
*
inode
=
d_backing_inode
(
dentry
);
return
inode
->
i_security
;
}
/*
* Get the security label of a dentry's backing inode.
*/
...
...
@@ -686,7 +693,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
struct
superblock_security_struct
*
sbsec
=
sb
->
s_security
;
const
char
*
name
=
sb
->
s_type
->
name
;
struct
dentry
*
root
=
sbsec
->
sb
->
s_root
;
struct
inode_security_struct
*
root_isec
=
backing_inode_security
(
root
)
;
struct
inode_security_struct
*
root_isec
;
u32
fscontext_sid
=
0
,
context_sid
=
0
,
rootcontext_sid
=
0
;
u32
defcontext_sid
=
0
;
char
**
mount_options
=
opts
->
mnt_opts
;
...
...
@@ -729,6 +736,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
&&
(
num_opts
==
0
))
goto
out
;
root_isec
=
backing_inode_security_novalidate
(
root
);
/*
* parse the mount options, check if they are valid sids.
* also check if someone is trying to mount the same sb more
...
...
@@ -1622,7 +1631,7 @@ static int current_has_perm(const struct task_struct *tsk,
/* Check whether a task is allowed to use a capability. */
static
int
cred_has_capability
(
const
struct
cred
*
cred
,
int
cap
,
int
audit
)
int
cap
,
int
audit
,
bool
initns
)
{
struct
common_audit_data
ad
;
struct
av_decision
avd
;
...
...
@@ -1636,10 +1645,10 @@ static int cred_has_capability(const struct cred *cred,
switch
(
CAP_TO_INDEX
(
cap
))
{
case
0
:
sclass
=
SECCLASS_CAPABILITY
;
sclass
=
initns
?
SECCLASS_CAPABILITY
:
SECCLASS_CAP_USERNS
;
break
;
case
1
:
sclass
=
SECCLASS_CAPABILITY2
;
sclass
=
initns
?
SECCLASS_CAPABILITY2
:
SECCLASS_CAP2_USERNS
;
break
;
default:
printk
(
KERN_ERR
...
...
@@ -1781,7 +1790,6 @@ static int selinux_determine_inode_label(struct inode *dir,
u32
*
_new_isid
)
{
const
struct
superblock_security_struct
*
sbsec
=
dir
->
i_sb
->
s_security
;
const
struct
inode_security_struct
*
dsec
=
inode_security
(
dir
);
const
struct
task_security_struct
*
tsec
=
current_security
();
if
((
sbsec
->
flags
&
SE_SBINITIALIZED
)
&&
...
...
@@ -1791,6 +1799,7 @@ static int selinux_determine_inode_label(struct inode *dir,
tsec
->
create_sid
)
{
*
_new_isid
=
tsec
->
create_sid
;
}
else
{
const
struct
inode_security_struct
*
dsec
=
inode_security
(
dir
);
return
security_transition_sid
(
tsec
->
sid
,
dsec
->
sid
,
tclass
,
name
,
_new_isid
);
}
...
...
@@ -2075,7 +2084,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
u32
sid
=
task_sid
(
to
);
struct
file_security_struct
*
fsec
=
file
->
f_security
;
struct
dentry
*
dentry
=
file
->
f_path
.
dentry
;
struct
inode_security_struct
*
isec
=
backing_inode_security
(
dentry
)
;
struct
inode_security_struct
*
isec
;
struct
common_audit_data
ad
;
int
rc
;
...
...
@@ -2094,6 +2103,7 @@ static int selinux_binder_transfer_file(struct task_struct *from,
if
(
unlikely
(
IS_PRIVATE
(
d_backing_inode
(
dentry
))))
return
0
;
isec
=
backing_inode_security
(
dentry
);
return
avc_has_perm
(
sid
,
isec
->
sid
,
isec
->
sclass
,
file_to_av
(
file
),
&
ad
);
}
...
...
@@ -2142,7 +2152,7 @@ static int selinux_capset(struct cred *new, const struct cred *old,
static
int
selinux_capable
(
const
struct
cred
*
cred
,
struct
user_namespace
*
ns
,
int
cap
,
int
audit
)
{
return
cred_has_capability
(
cred
,
cap
,
audit
);
return
cred_has_capability
(
cred
,
cap
,
audit
,
ns
==
&
init_user_ns
);
}
static
int
selinux_quotactl
(
int
cmds
,
int
type
,
int
id
,
struct
super_block
*
sb
)
...
...
@@ -2220,7 +2230,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
int
rc
,
cap_sys_admin
=
0
;
rc
=
cred_has_capability
(
current_cred
(),
CAP_SYS_ADMIN
,
SECURITY_CAP_NOAUDIT
);
SECURITY_CAP_NOAUDIT
,
true
);
if
(
rc
==
0
)
cap_sys_admin
=
1
;
...
...
@@ -2229,6 +2239,20 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
/* binprm security operations */
static
u32
ptrace_parent_sid
(
struct
task_struct
*
task
)
{
u32
sid
=
0
;
struct
task_struct
*
tracer
;
rcu_read_lock
();
tracer
=
ptrace_parent
(
task
);
if
(
tracer
)
sid
=
task_sid
(
tracer
);
rcu_read_unlock
();
return
sid
;
}
static
int
check_nnp_nosuid
(
const
struct
linux_binprm
*
bprm
,
const
struct
task_security_struct
*
old_tsec
,
const
struct
task_security_struct
*
new_tsec
)
...
...
@@ -2350,18 +2374,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
* changes its SID has the appropriate permit */
if
(
bprm
->
unsafe
&
(
LSM_UNSAFE_PTRACE
|
LSM_UNSAFE_PTRACE_CAP
))
{
struct
task_struct
*
tracer
;
struct
task_security_struct
*
sec
;
u32
ptsid
=
0
;
rcu_read_lock
();
tracer
=
ptrace_parent
(
current
);
if
(
likely
(
tracer
!=
NULL
))
{
sec
=
__task_cred
(
tracer
)
->
security
;
ptsid
=
sec
->
sid
;
}
rcu_read_unlock
();
u32
ptsid
=
ptrace_parent_sid
(
current
);
if
(
ptsid
!=
0
)
{
rc
=
avc_has_perm
(
ptsid
,
new_tsec
->
sid
,
SECCLASS_PROCESS
,
...
...
@@ -3045,7 +3058,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
const
void
*
value
,
size_t
size
,
int
flags
)
{
struct
inode
*
inode
=
d_backing_inode
(
dentry
);
struct
inode_security_struct
*
isec
=
backing_inode_security
(
dentry
)
;
struct
inode_security_struct
*
isec
;
struct
superblock_security_struct
*
sbsec
;
struct
common_audit_data
ad
;
u32
newsid
,
sid
=
current_sid
();
...
...
@@ -3064,6 +3077,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
ad
.
type
=
LSM_AUDIT_DATA_DENTRY
;
ad
.
u
.
dentry
=
dentry
;
isec
=
backing_inode_security
(
dentry
);
rc
=
avc_has_perm
(
sid
,
isec
->
sid
,
isec
->
sclass
,
FILE__RELABELFROM
,
&
ad
);
if
(
rc
)
...
...
@@ -3122,7 +3136,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
int
flags
)
{
struct
inode
*
inode
=
d_backing_inode
(
dentry
);
struct
inode_security_struct
*
isec
=
backing_inode_security
(
dentry
)
;
struct
inode_security_struct
*
isec
;
u32
newsid
;
int
rc
;
...
...
@@ -3139,6 +3153,7 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
return
;
}
isec
=
backing_inode_security
(
dentry
);
isec
->
sclass
=
inode_mode_to_security_class
(
inode
->
i_mode
);
isec
->
sid
=
newsid
;
isec
->
initialized
=
LABEL_INITIALIZED
;
...
...
@@ -3180,7 +3195,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
u32
size
;
int
error
;
char
*
context
=
NULL
;
struct
inode_security_struct
*
isec
=
inode_security
(
inode
)
;
struct
inode_security_struct
*
isec
;
if
(
strcmp
(
name
,
XATTR_SELINUX_SUFFIX
))
return
-
EOPNOTSUPP
;
...
...
@@ -3198,7 +3213,8 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
SECURITY_CAP_NOAUDIT
);
if
(
!
error
)
error
=
cred_has_capability
(
current_cred
(),
CAP_MAC_ADMIN
,
SECURITY_CAP_NOAUDIT
);
SECURITY_CAP_NOAUDIT
,
true
);
isec
=
inode_security
(
inode
);
if
(
!
error
)
error
=
security_sid_to_context_force
(
isec
->
sid
,
&
context
,
&
size
);
...
...
@@ -3219,7 +3235,7 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
static
int
selinux_inode_setsecurity
(
struct
inode
*
inode
,
const
char
*
name
,
const
void
*
value
,
size_t
size
,
int
flags
)
{
struct
inode_security_struct
*
isec
=
inode_security
(
inode
);
struct
inode_security_struct
*
isec
=
inode_security
_novalidate
(
inode
);
u32
newsid
;
int
rc
;
...
...
@@ -3308,7 +3324,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
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_security
(
inode
)
;
struct
inode_security_struct
*
isec
;
struct
lsm_ioctlop_audit
ioctl
;
u32
ssid
=
cred_sid
(
cred
);
int
rc
;
...
...
@@ -3332,6 +3348,7 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
if
(
unlikely
(
IS_PRIVATE
(
inode
)))
return
0
;
isec
=
inode_security
(
inode
);
rc
=
avc_has_extended_perms
(
ssid
,
isec
->
sid
,
isec
->
sclass
,
requested
,
driver
,
xperm
,
&
ad
);
out:
...
...
@@ -3373,7 +3390,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
case
KDSKBENT
:
case
KDSKBSENT
:
error
=
cred_has_capability
(
cred
,
CAP_SYS_TTY_CONFIG
,
SECURITY_CAP_AUDIT
);
SECURITY_CAP_AUDIT
,
true
);
break
;
/* default case assumes that the command will go
...
...
@@ -3462,8 +3479,9 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
vma
->
vm_end
<=
vma
->
vm_mm
->
brk
)
{
rc
=
cred_has_perm
(
cred
,
cred
,
PROCESS__EXECHEAP
);
}
else
if
(
!
vma
->
vm_file
&&
vma
->
vm_start
<=
vma
->
vm_mm
->
start_stack
&&
vma
->
vm_end
>=
vma
->
vm_mm
->
start_stack
)
{
((
vma
->
vm_start
<=
vma
->
vm_mm
->
start_stack
&&
vma
->
vm_end
>=
vma
->
vm_mm
->
start_stack
)
||
vma_is_stack_for_task
(
vma
,
current
)))
{
rc
=
current_has_perm
(
current
,
PROCESS__EXECSTACK
);
}
else
if
(
vma
->
vm_file
&&
vma
->
anon_vma
)
{
/*
...
...
@@ -3719,6 +3737,52 @@ static int selinux_kernel_module_request(char *kmod_name)
SYSTEM__MODULE_REQUEST
,
&
ad
);
}
static
int
selinux_kernel_module_from_file
(
struct
file
*
file
)
{
struct
common_audit_data
ad
;
struct
inode_security_struct
*
isec
;
struct
file_security_struct
*
fsec
;
u32
sid
=
current_sid
();
int
rc
;
/* init_module */
if
(
file
==
NULL
)
return
avc_has_perm
(
sid
,
sid
,
SECCLASS_SYSTEM
,
SYSTEM__MODULE_LOAD
,
NULL
);
/* finit_module */
ad
.
type
=
LSM_AUDIT_DATA_PATH
;
ad
.
u
.
path
=
file
->
f_path
;
fsec
=
file
->
f_security
;
if
(
sid
!=
fsec
->
sid
)
{
rc
=
avc_has_perm
(
sid
,
fsec
->
sid
,
SECCLASS_FD
,
FD__USE
,
&
ad
);
if
(
rc
)
return
rc
;
}
isec
=
inode_security
(
file_inode
(
file
));
return
avc_has_perm
(
sid
,
isec
->
sid
,
SECCLASS_SYSTEM
,
SYSTEM__MODULE_LOAD
,
&
ad
);
}
static
int
selinux_kernel_read_file
(
struct
file
*
file
,
enum
kernel_read_file_id
id
)
{
int
rc
=
0
;
switch
(
id
)
{
case
READING_MODULE
:
rc
=
selinux_kernel_module_from_file
(
file
);
break
;
default:
break
;
}
return
rc
;
}
static
int
selinux_task_setpgid
(
struct
task_struct
*
p
,
pid_t
pgid
)
{
return
current_has_perm
(
p
,
PROCESS__SETPGID
);
...
...
@@ -4598,6 +4662,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
{
u32
peer_secid
=
SECSID_NULL
;
u16
family
;
struct
inode_security_struct
*
isec
;
if
(
skb
&&
skb
->
protocol
==
htons
(
ETH_P_IP
))
family
=
PF_INET
;
...
...
@@ -4608,9 +4673,10 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
else
goto
out
;
if
(
sock
&&
family
==
PF_UNIX
)
selinux_inode_getsecid
(
SOCK_INODE
(
sock
),
&
peer_secid
);
else
if
(
skb
)
if
(
sock
&&
family
==
PF_UNIX
)
{
isec
=
inode_security_novalidate
(
SOCK_INODE
(
sock
));
peer_secid
=
isec
->
sid
;
}
else
if
(
skb
)
selinux_skb_peerlbl_sid
(
skb
,
family
,
&
peer_secid
);
out:
...
...
@@ -5675,7 +5741,6 @@ static int selinux_setprocattr(struct task_struct *p,
char
*
name
,
void
*
value
,
size_t
size
)
{
struct
task_security_struct
*
tsec
;
struct
task_struct
*
tracer
;
struct
cred
*
new
;
u32
sid
=
0
,
ptsid
;
int
error
;
...
...
@@ -5782,14 +5847,8 @@ static int selinux_setprocattr(struct task_struct *p,
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and fail. */
ptsid
=
0
;
rcu_read_lock
();
tracer
=
ptrace_parent
(
p
);
if
(
tracer
)
ptsid
=
task_sid
(
tracer
);
rcu_read_unlock
();
if
(
tracer
)
{
ptsid
=
ptrace_parent_sid
(
p
);
if
(
ptsid
!=
0
)
{
error
=
avc_has_perm
(
ptsid
,
sid
,
SECCLASS_PROCESS
,
PROCESS__PTRACE
,
NULL
);
if
(
error
)
...
...
@@ -6020,6 +6079,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT
(
kernel_act_as
,
selinux_kernel_act_as
),
LSM_HOOK_INIT
(
kernel_create_files_as
,
selinux_kernel_create_files_as
),
LSM_HOOK_INIT
(
kernel_module_request
,
selinux_kernel_module_request
),
LSM_HOOK_INIT
(
kernel_read_file
,
selinux_kernel_read_file
),
LSM_HOOK_INIT
(
task_setpgid
,
selinux_task_setpgid
),
LSM_HOOK_INIT
(
task_getpgid
,
selinux_task_getpgid
),
LSM_HOOK_INIT
(
task_getsid
,
selinux_task_getsid
),
...
...
security/selinux/include/classmap.h
View file @
a6926cc9
...
...
@@ -12,6 +12,18 @@
#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \
"write", "associate", "unix_read", "unix_write"
#define COMMON_CAP_PERMS "chown", "dac_override", "dac_read_search", \
"fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", \
"linux_immutable", "net_bind_service", "net_broadcast", \
"net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", \
"sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", \
"sys_boot", "sys_nice", "sys_resource", "sys_time", \
"sys_tty_config", "mknod", "lease", "audit_write", \
"audit_control", "setfcap"
#define COMMON_CAP2_PERMS "mac_override", "mac_admin", "syslog", \
"wake_alarm", "block_suspend", "audit_read"
/*
* Note: The name for any socket class should be suffixed by "socket",
* and doesn't contain more than one substr of "socket".
...
...
@@ -32,16 +44,9 @@ struct security_class_mapping secclass_map[] = {
"setsockcreate"
,
NULL
}
},
{
"system"
,
{
"ipc_info"
,
"syslog_read"
,
"syslog_mod"
,
"syslog_console"
,
"module_request"
,
NULL
}
},
"syslog_console"
,
"module_request"
,
"module_load"
,
NULL
}
},
{
"capability"
,
{
"chown"
,
"dac_override"
,
"dac_read_search"
,
"fowner"
,
"fsetid"
,
"kill"
,
"setgid"
,
"setuid"
,
"setpcap"
,
"linux_immutable"
,
"net_bind_service"
,
"net_broadcast"
,
"net_admin"
,
"net_raw"
,
"ipc_lock"
,
"ipc_owner"
,
"sys_module"
,
"sys_rawio"
,
"sys_chroot"
,
"sys_ptrace"
,
"sys_pacct"
,
"sys_admin"
,
"sys_boot"
,
"sys_nice"
,
"sys_resource"
,
"sys_time"
,
"sys_tty_config"
,
"mknod"
,
"lease"
,
"audit_write"
,
"audit_control"
,
"setfcap"
,
NULL
}
},
{
COMMON_CAP_PERMS
,
NULL
}
},
{
"filesystem"
,
{
"mount"
,
"remount"
,
"unmount"
,
"getattr"
,
"relabelfrom"
,
"relabelto"
,
"associate"
,
"quotamod"
,
...
...
@@ -150,12 +155,15 @@ struct security_class_mapping secclass_map[] = {
{
"memprotect"
,
{
"mmap_zero"
,
NULL
}
},
{
"peer"
,
{
"recv"
,
NULL
}
},
{
"capability2"
,
{
"mac_override"
,
"mac_admin"
,
"syslog"
,
"wake_alarm"
,
"block_suspend"
,
"audit_read"
,
NULL
}
},
{
COMMON_CAP2_PERMS
,
NULL
}
},
{
"kernel_service"
,
{
"use_as_override"
,
"create_files_as"
,
NULL
}
},
{
"tun_socket"
,
{
COMMON_SOCK_PERMS
,
"attach_queue"
,
NULL
}
},
{
"binder"
,
{
"impersonate"
,
"call"
,
"set_context_mgr"
,
"transfer"
,
NULL
}
},
{
"cap_userns"
,
{
COMMON_CAP_PERMS
,
NULL
}
},
{
"cap2_userns"
,
{
COMMON_CAP2_PERMS
,
NULL
}
},
{
NULL
}
};
security/selinux/include/conditional.h
View file @
a6926cc9
...
...
@@ -17,6 +17,6 @@ int security_get_bools(int *len, char ***names, int **values);
int
security_set_bools
(
int
len
,
int
*
values
);
int
security_get_bool_value
(
int
bool
);
int
security_get_bool_value
(
int
index
);
#endif
security/selinux/include/objsec.h
View file @
a6926cc9
...
...
@@ -38,9 +38,8 @@ struct task_security_struct {
};
enum
label_initialized
{
LABEL_MISSING
,
/* not initialized */
LABEL_INITIALIZED
,
/* inizialized */
LABEL_INVALID
/* invalid */
LABEL_INVALID
,
/* invalid or not initialized */
LABEL_INITIALIZED
/* initialized */
};
struct
inode_security_struct
{
...
...
security/selinux/ss/services.c
View file @
a6926cc9
...
...
@@ -2696,7 +2696,7 @@ int security_set_bools(int len, int *values)
return
rc
;
}
int
security_get_bool_value
(
int
bool
)
int
security_get_bool_value
(
int
index
)
{
int
rc
;
int
len
;
...
...
@@ -2705,10 +2705,10 @@ int security_get_bool_value(int bool)
rc
=
-
EFAULT
;
len
=
policydb
.
p_bools
.
nprim
;
if
(
bool
>=
len
)
if
(
index
>=
len
)
goto
out
;
rc
=
policydb
.
bool_val_to_struct
[
bool
]
->
state
;
rc
=
policydb
.
bool_val_to_struct
[
index
]
->
state
;
out:
read_unlock
(
&
policy_rwlock
);
return
rc
;
...
...
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