mirror of
https://github.com/SELinuxProject/selinux
synced 2024-12-26 16:02:26 +00:00
This patch enables applications to handle permissive domain correctly.
Since the v2.6.26 kernel, SELinux has supported an idea of permissive domain which allows certain processes to work as if permissive mode, even if the global setting is enforcing mode. However, we don't have an application program interface to inform what domains are permissive one, and what domains are not. It means applications focuses on SELinux (XACE/SELinux, SE-PostgreSQL and so on) cannot handle permissive domain correctly. This patch add the sixth field (flags) on the reply of the /selinux/access interface which is used to make an access control decision from userspace. If the first bit of the flags field is positive, it means the required access control decision is on permissive domain, so application should allow any required actions, as the kernel doing. This patch also has a side benefit. The av_decision.flags is set at context_struct_compute_av(). It enables to check required permissions without read_lock(&policy_rwlock). Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
This commit is contained in:
parent
318748d659
commit
55ed6e7fa6
@ -130,8 +130,12 @@ struct av_decision {
|
||||
access_vector_t auditallow;
|
||||
access_vector_t auditdeny;
|
||||
unsigned int seqno;
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/* Definitions of av_decision.flags */
|
||||
#define SELINUX_AVD_FLAGS_PERMISSIVE 0x0001
|
||||
|
||||
/* Structure for passing options, used by AVC and label subsystems */
|
||||
struct selinux_opt {
|
||||
int type;
|
||||
@ -186,6 +190,17 @@ extern int security_compute_av_raw(security_context_t scon,
|
||||
access_vector_t requested,
|
||||
struct av_decision *avd);
|
||||
|
||||
extern int security_compute_av_flags(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested,
|
||||
struct av_decision *avd);
|
||||
extern int security_compute_av_flags_raw(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested,
|
||||
struct av_decision *avd);
|
||||
|
||||
/* Compute a labeling decision and set *newcon to refer to it.
|
||||
Caller must free via freecon. */
|
||||
extern int security_compute_create(security_context_t scon,
|
||||
|
@ -1,6 +1,6 @@
|
||||
.TH "security_compute_av" "3" "1 January 2004" "russell@coker.com.au" "SELinux API documentation"
|
||||
.SH "NAME"
|
||||
security_compute_av, security_compute_create, security_compute_relabel,
|
||||
security_compute_av, security_compute_av_flags, security_compute_create, security_compute_relabel,
|
||||
security_compute_member, security_compute_user, security_get_initial_context \- query
|
||||
the SELinux policy database in the kernel.
|
||||
|
||||
@ -11,6 +11,8 @@ the SELinux policy database in the kernel.
|
||||
.sp
|
||||
.BI "int security_compute_av(security_context_t "scon ", security_context_t "tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd );
|
||||
.sp
|
||||
.BI "int security_compute_av_flags(security_context_t "scon ", security_context_t "tcon ", security_class_t "tclass ", access_vector_t "requested ", struct av_decision *" avd );
|
||||
.sp
|
||||
.BI "int security_compute_create(security_context_t "scon ", security_context_t "tcon ", security_class_t "tclass ", security_context_t *" newcon );
|
||||
.sp
|
||||
.BI "int security_compute_relabel(security_context_t "scon ", security_context_t "tcon ", security_class_t "tclass ", security_context_t *" newcon );
|
||||
@ -34,7 +36,19 @@ via class
|
||||
.B tclass
|
||||
with the
|
||||
.B requested
|
||||
access vector. See the cron source for a usage example.
|
||||
access vector. The decision is returned in
|
||||
.BR avd .
|
||||
|
||||
.B security_compute_av_flags
|
||||
is identical to
|
||||
.B security_compute_av
|
||||
but additionally sets the
|
||||
.B flags
|
||||
field of
|
||||
.BR avd .
|
||||
Currently one flag is supported:
|
||||
.BR SELINUX_AVD_FLAGS_PERMISSIVE ,
|
||||
which indicates the decision is computed on a permissive domain.
|
||||
|
||||
.B security_compute_create
|
||||
is used to compute a context to use for labeling a new object in a particular
|
||||
|
1
libselinux/man/man3/security_compute_av_flags.3
Normal file
1
libselinux/man/man3/security_compute_av_flags.3
Normal file
@ -0,0 +1 @@
|
||||
.so man3/security_compute_av.3
|
@ -849,9 +849,9 @@ int avc_has_perm_noaudit(security_id_t ssid,
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
rc = security_compute_av_raw(ssid->ctx, tsid->ctx,
|
||||
tclass, requested,
|
||||
&entry.avd);
|
||||
rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
|
||||
tclass, requested,
|
||||
&entry.avd);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = avc_insert(ssid, tsid, tclass, &entry, aeref);
|
||||
@ -867,11 +867,13 @@ int avc_has_perm_noaudit(security_id_t ssid,
|
||||
denied = requested & ~(ae->avd.allowed);
|
||||
|
||||
if (!requested || denied) {
|
||||
if (avc_enforcing) {
|
||||
if (!avc_enforcing ||
|
||||
(ae->avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE))
|
||||
ae->avd.allowed |= requested;
|
||||
else {
|
||||
errno = EACCES;
|
||||
rc = -1;
|
||||
} else
|
||||
ae->avd.allowed |= requested;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
@ -885,9 +887,11 @@ int avc_has_perm(security_id_t ssid, security_id_t tsid,
|
||||
security_class_t tclass, access_vector_t requested,
|
||||
struct avc_entry_ref *aeref, void *auditdata)
|
||||
{
|
||||
struct av_decision avd = { 0, 0, 0, 0, 0 };
|
||||
struct av_decision avd;
|
||||
int errsave, rc;
|
||||
|
||||
memset(&avd, 0, sizeof(avd));
|
||||
|
||||
rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, aeref, &avd);
|
||||
errsave = errno;
|
||||
avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
|
||||
@ -917,8 +921,8 @@ int avc_compute_create(security_id_t ssid, security_id_t tsid,
|
||||
rc = avc_lookup(ssid, tsid, tclass, 0, &aeref);
|
||||
if (rc) {
|
||||
/* need to make a cache entry for this tuple */
|
||||
rc = security_compute_av_raw(ssid->ctx, tsid->ctx,
|
||||
tclass, 0, &entry.avd);
|
||||
rc = security_compute_av_flags_raw(ssid->ctx, tsid->ctx,
|
||||
tclass, 0, &entry.avd);
|
||||
if (rc)
|
||||
goto out;
|
||||
rc = avc_insert(ssid, tsid, tclass, &entry, &aeref);
|
||||
|
@ -10,10 +10,11 @@
|
||||
#include "policy.h"
|
||||
#include "mapping.h"
|
||||
|
||||
int security_compute_av_raw(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested, struct av_decision *avd)
|
||||
int security_compute_av_flags_raw(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested,
|
||||
struct av_decision *avd)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char *buf;
|
||||
@ -49,12 +50,15 @@ int security_compute_av_raw(security_context_t scon,
|
||||
if (ret < 0)
|
||||
goto out2;
|
||||
|
||||
if (sscanf(buf, "%x %x %x %x %u", &avd->allowed,
|
||||
&avd->decided, &avd->auditallow, &avd->auditdeny,
|
||||
&avd->seqno) != 5) {
|
||||
ret = sscanf(buf, "%x %x %x %x %u %x",
|
||||
&avd->allowed, &avd->decided,
|
||||
&avd->auditallow, &avd->auditdeny,
|
||||
&avd->seqno, &avd->flags);
|
||||
if (ret < 5) {
|
||||
ret = -1;
|
||||
goto out2;
|
||||
}
|
||||
} else if (ret < 6)
|
||||
avd->flags = 0;
|
||||
|
||||
map_decision(tclass, avd);
|
||||
|
||||
@ -66,16 +70,44 @@ int security_compute_av_raw(security_context_t scon,
|
||||
return ret;
|
||||
}
|
||||
|
||||
hidden_def(security_compute_av_flags_raw)
|
||||
|
||||
int security_compute_av_raw(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested,
|
||||
struct av_decision *avd)
|
||||
{
|
||||
struct av_decision lavd;
|
||||
int ret;
|
||||
|
||||
ret = security_compute_av_flags_raw(scon, tcon, tclass,
|
||||
requested, &lavd);
|
||||
if (ret == 0) {
|
||||
avd->allowed = lavd.allowed;
|
||||
avd->decided = lavd.decided;
|
||||
avd->auditallow = lavd.auditallow;
|
||||
avd->auditdeny = lavd.auditdeny;
|
||||
avd->seqno = lavd.seqno;
|
||||
/* NOTE:
|
||||
* We should not return avd->flags via the interface
|
||||
* due to the binary compatibility.
|
||||
*/
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
hidden_def(security_compute_av_raw)
|
||||
|
||||
int security_compute_av(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested, struct av_decision *avd)
|
||||
int security_compute_av_flags(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested,
|
||||
struct av_decision *avd)
|
||||
{
|
||||
int ret;
|
||||
security_context_t rscon = scon;
|
||||
security_context_t rtcon = tcon;
|
||||
int ret;
|
||||
|
||||
if (selinux_trans_to_raw_context(scon, &rscon))
|
||||
return -1;
|
||||
@ -83,8 +115,8 @@ int security_compute_av(security_context_t scon,
|
||||
freecon(rscon);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = security_compute_av_raw(rscon, rtcon, tclass, requested, avd);
|
||||
ret = security_compute_av_flags_raw(rscon, rtcon, tclass,
|
||||
requested, avd);
|
||||
|
||||
freecon(rscon);
|
||||
freecon(rtcon);
|
||||
@ -92,4 +124,32 @@ int security_compute_av(security_context_t scon,
|
||||
return ret;
|
||||
}
|
||||
|
||||
hidden_def(security_compute_av_flags)
|
||||
|
||||
int security_compute_av(security_context_t scon,
|
||||
security_context_t tcon,
|
||||
security_class_t tclass,
|
||||
access_vector_t requested, struct av_decision *avd)
|
||||
{
|
||||
struct av_decision lavd;
|
||||
int ret;
|
||||
|
||||
ret = security_compute_av_flags(scon, tcon, tclass,
|
||||
requested, &lavd);
|
||||
if (ret == 0)
|
||||
{
|
||||
avd->allowed = lavd.allowed;
|
||||
avd->decided = lavd.decided;
|
||||
avd->auditallow = lavd.auditallow;
|
||||
avd->auditdeny = lavd.auditdeny;
|
||||
avd->seqno = lavd.seqno;
|
||||
/* NOTE:
|
||||
* We should not return avd->flags via the interface
|
||||
* due to the binary compatibility.
|
||||
*/
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hidden_def(security_compute_av)
|
||||
|
@ -16,6 +16,8 @@ hidden_proto(selinux_mkload_policy)
|
||||
hidden_proto(security_canonicalize_context_raw)
|
||||
hidden_proto(security_compute_av)
|
||||
hidden_proto(security_compute_av_raw)
|
||||
hidden_proto(security_compute_av_flags)
|
||||
hidden_proto(security_compute_av_flags_raw)
|
||||
hidden_proto(security_compute_user)
|
||||
hidden_proto(security_compute_user_raw)
|
||||
hidden_proto(security_compute_create)
|
||||
|
Loading…
Reference in New Issue
Block a user