Discussion:
genfs_contexts and /proc/PID files
Nick Kralevich
2015-03-07 18:57:17 UTC
Permalink
I'm trying to figure out how to label a file in /proc/PID with a different
SELinux label. In particular, I'm trying to apply an SELinux label to the
file /proc/PID/oom_score_adj .

I thought this would be easy to do by adding the following line to
genfs_contexts:

genfscon proc /oom_score_adj u:object_r:MY_NEW_LABEL:s0

but this doesn't seem to be working. /proc/PID/oom_score_adj continues to
be labeled with the process' label.

***@flounder:/ $ ls -laZ /proc/self/oom_score_adj
-rw-r--r-- shell shell u:r:shell:s0 oom_score_adj

My understanding was that, for /proc, the numeric portion of the path was
ignored, and genfscon paths could be relative to the top of the /proc/PID
directory. Quoting linux/security/selinux/hooks.c

else {
/* each process gets a /proc/PID/ entry. Strip off the
* PID part to get a valid selinux labeling.
* e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
while (path[1] >= '0' && path[1] <= '9') {
path[1] = '/';
path++;
}
rc = security_genfs_sid("proc", path, tclass, sid);
}
free_page((unsigned long)buffer);

This logic seems to work for /proc/PID/net, since the files in that
directory (but not the directory itself) are labeled with
u:object_r:proc_net:s0 . And it seems to work for subdirectories of
/proc/PID/net, in particular /proc/PID/net/xt_qtaguid/ctrl in Android is
labeled as u:object_r:qtaguid_proc:s0 . However, it doesn't seem to work
for files in /proc/PID itself.

I've briefly looked through the SELinux code which handles /proc/PID
labeling, but it's unclear to me how this code actually works, and how the
/proc/PID labels are even created in the first place. The first genfscon
proc rule is:

genfscon proc / u:object_r:proc:s0

which, if the comment in the code is to be believed, should make all
/proc/PID files labeled with "u:object_r:proc:s0". That's obviously not the
case...

So, my questions are:

1) How do I get a custom label on a file in /proc/PID ?

2) How does the genfscon statements in the policy interact with /proc/PID
labeling? Are genfscon statements even consulted at all? And if not, how
does /proc/PID/net labeling work?

Thanks,
-- Nick
--
Nick Kralevich | Android Security | ***@google.com | 650.214.4037
Stephen Smalley
2015-03-09 15:28:38 UTC
Permalink
Post by Nick Kralevich
I'm trying to figure out how to label a file in /proc/PID with a
different SELinux label. In particular, I'm trying to apply an SELinux
label to the file /proc/PID/oom_score_adj .
I thought this would be easy to do by adding the following line to
genfscon proc /oom_score_adj u:object_r:MY_NEW_LABEL:s0
but this doesn't seem to be working. /proc/PID/oom_score_adj continues
to be labeled with the process' label.
-rw-r--r-- shell shell u:r:shell:s0 oom_score_adj
My understanding was that, for /proc, the numeric portion of the path
was ignored, and genfscon paths could be relative to the top of the
/proc/PID directory. Quoting linux/security/selinux/hooks.c
else {
/* each process gets a /proc/PID/ entry. Strip off the
* PID part to get a valid selinux labeling.
* e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
while (path[1] >= '0' && path[1] <= '9') {
path[1] = '/';
path++;
}
rc = security_genfs_sid("proc", path, tclass, sid);
}
free_page((unsigned long)buffer);
This logic seems to work for /proc/PID/net, since the files in that
directory (but not the directory itself) are labeled with
u:object_r:proc_net:s0 . And it seems to work for subdirectories of
/proc/PID/net, in particular /proc/PID/net/xt_qtaguid/ctrl in Android is
labeled as u:object_r:qtaguid_proc:s0 . However, it doesn't seem to work
for files in /proc/PID itself.
I've briefly looked through the SELinux code which handles /proc/PID
labeling, but it's unclear to me how this code actually works, and how
the /proc/PID labels are even created in the first place. The first
genfscon proc / u:object_r:proc:s0
which, if the comment in the code is to be believed, should make all
/proc/PID files labeled with "u:object_r:proc:s0". That's obviously not
the case...
1) How do I get a custom label on a file in /proc/PID ?
2) How does the genfscon statements in the policy interact with
/proc/PID labeling? Are genfscon statements even consulted at all? And
if not, how does /proc/PID/net labeling work?
genfs_contexts is (or was originally) only used for /proc labeling
outside of /proc/pid. /proc/pid inodes are labeled based on the
associated task by the selinux_task_to_inode() hook function, called by
security_task_to_inode(), called by proc_pid_make_inode() and
pid_revalidate(). This happens upon inode creation, before association
with a dentry/name, so it cannot be name-based presently. It is always
just the context of the associated task for all /proc/pid nodes.

/proc/pid/net was originally /proc/net (i.e. was global rather than
per-process, prior to introduction of network namespaces) and thus was
labeled via genfs_contexts. When they virtualized /proc/net, the
SELinux logic had to be adjusted to preserve compatibility in labeling
even though it fell under /proc/pid. The /proc/pid/net files are not
assigned the uid/gid of the associated task so it is consistent to label
them with global SELinux domains/types rather than the task domain. The
proc/pid/net inodes are not created via proc_pid_make_inode() and thus
their isec initialization does not occur at that time, but rather later
upon association with a dentry, when they have a name.

We have considered supporting finer granularity on labeling the
/proc/pid inodes in the past but there hasn't been a compelling case for
it to date. It would require a kernel change.
Stephen Smalley
2015-03-10 16:34:30 UTC
Permalink
Post by Stephen Smalley
Post by Nick Kralevich
I'm trying to figure out how to label a file in /proc/PID with a
different SELinux label. In particular, I'm trying to apply an SELinux
label to the file /proc/PID/oom_score_adj .
I thought this would be easy to do by adding the following line to
genfscon proc /oom_score_adj u:object_r:MY_NEW_LABEL:s0
but this doesn't seem to be working. /proc/PID/oom_score_adj continues
to be labeled with the process' label.
-rw-r--r-- shell shell u:r:shell:s0 oom_score_adj
My understanding was that, for /proc, the numeric portion of the path
was ignored, and genfscon paths could be relative to the top of the
/proc/PID directory. Quoting linux/security/selinux/hooks.c
else {
/* each process gets a /proc/PID/ entry. Strip off the
* PID part to get a valid selinux labeling.
* e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */
while (path[1] >= '0' && path[1] <= '9') {
path[1] = '/';
path++;
}
rc = security_genfs_sid("proc", path, tclass, sid);
}
free_page((unsigned long)buffer);
This logic seems to work for /proc/PID/net, since the files in that
directory (but not the directory itself) are labeled with
u:object_r:proc_net:s0 . And it seems to work for subdirectories of
/proc/PID/net, in particular /proc/PID/net/xt_qtaguid/ctrl in Android is
labeled as u:object_r:qtaguid_proc:s0 . However, it doesn't seem to work
for files in /proc/PID itself.
I've briefly looked through the SELinux code which handles /proc/PID
labeling, but it's unclear to me how this code actually works, and how
the /proc/PID labels are even created in the first place. The first
genfscon proc / u:object_r:proc:s0
which, if the comment in the code is to be believed, should make all
/proc/PID files labeled with "u:object_r:proc:s0". That's obviously not
the case...
1) How do I get a custom label on a file in /proc/PID ?
2) How does the genfscon statements in the policy interact with
/proc/PID labeling? Are genfscon statements even consulted at all? And
if not, how does /proc/PID/net labeling work?
genfs_contexts is (or was originally) only used for /proc labeling
outside of /proc/pid. /proc/pid inodes are labeled based on the
associated task by the selinux_task_to_inode() hook function, called by
security_task_to_inode(), called by proc_pid_make_inode() and
pid_revalidate(). This happens upon inode creation, before association
with a dentry/name, so it cannot be name-based presently. It is always
just the context of the associated task for all /proc/pid nodes.
/proc/pid/net was originally /proc/net (i.e. was global rather than
per-process, prior to introduction of network namespaces) and thus was
labeled via genfs_contexts. When they virtualized /proc/net, the
SELinux logic had to be adjusted to preserve compatibility in labeling
even though it fell under /proc/pid. The /proc/pid/net files are not
assigned the uid/gid of the associated task so it is consistent to label
them with global SELinux domains/types rather than the task domain. The
proc/pid/net inodes are not created via proc_pid_make_inode() and thus
their isec initialization does not occur at that time, but rather later
upon association with a dentry, when they have a name.
We have considered supporting finer granularity on labeling the
/proc/pid inodes in the past but there hasn't been a compelling case for
it to date. It would require a kernel change.
Also, if we were to make such a change, typically we would compute a
context for the /proc/pid inode via security_transition_sid() so that we
can take into account both the associated task context and optionally
the name, since these /proc/pid nodes contain task-private state and
should usually reflect the task security context in some manner. Then
we could define name-based type transitions for example to specify
finer-grained labeling in policy. I doubt we would use genfs_contexts,
as that is only name based and cannot take into account the task context.
Loading...