libselinux: refactor AVC netlink code
PATCH 1/1 libselinux: refactor AVC netlink code
This patch removes duplication in the AVC netlink code by introducing helper functions.
Did some basic testing and confirmed that messages are received and processed.
More patches to follow.
---
avc_internal.c | 289 +++++++++++++++++++++------------------------------------
1 file changed, 107 insertions(+), 182 deletions(-)
src/avc_internal.c +0 -0
@@ -89,221 +89,146 @@
close(fd); }
-int avc_netlink_check_nb(void)
+static int avc_netlink_receive(char *buf, unsigned buflen)
{
int rc;
struct sockaddr_nl nladdr;
socklen_t nladdrlen = sizeof nladdr;- char buf[1024];
- struct nlmsghdr *nlh;
+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
- while (1) {
- rc = recvfrom(fd, buf, sizeof(buf), 0,
- (struct sockaddr *)&nladdr, &nladdrlen);
- if (rc < 0) {
- if (errno == EINTR)
- continue;
- if (errno != EAGAIN) {
- avc_log("%s: socket error during read: %d\n",
- avc_prefix, errno);
- } else {
- errno = 0;
- rc = 0;
- }
- goto out;
- }
+ rc = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&nladdr,
+ &nladdrlen);
+ if (rc < 0)
+ return rc;
- if (nladdrlen != sizeof nladdr) {
- avc_log
- ("%s: warning: netlink address truncated, len %d?\n",
- avc_prefix, nladdrlen);
- rc = -1;
- goto out;
- }
+ if (nladdrlen != sizeof nladdr) {
+ avc_log("%s: warning: netlink address truncated, len %d?\n",
+ avc_prefix, nladdrlen);
+ return -1;
+ }
- if (nladdr.nl_pid) {
- avc_log
- ("%s: warning: received spoofed netlink packet from: %d\n",
- avc_prefix, nladdr.nl_pid);
- continue;
- }
+ if (nladdr.nl_pid) {
+ avc_log("%s: warning: received spoofed netlink packet from: %d\n",
+ avc_prefix, nladdr.nl_pid);
+ return -1;
+ }
- if (rc == 0) {
- avc_log("%s: warning: received EOF on socket\n",
- avc_prefix);
- goto out;
- }
+ if (rc == 0) {
+ avc_log("%s: warning: received EOF on netlink socket\n",
+ avc_prefix);
+ errno = EBADFD;
+ return -1;
+ }
- nlh = (struct nlmsghdr *)buf;
+ if (nlh->nlmsg_flags & MSG_TRUNC || nlh->nlmsg_len > (unsigned)rc) {
+ avc_log("%s: warning: incomplete netlink message\n",
+ avc_prefix);
+ return -1;
+ }
- if (nlh->nlmsg_flags & MSG_TRUNC
- || nlh->nlmsg_len > (unsigned)rc) {
- avc_log("%s: warning: incomplete netlink message\n",
- avc_prefix);
- goto out;
- }
+ return 0;
+}
- rc = 0;
- switch (nlh->nlmsg_type) {
- case NLMSG_ERROR:{
- struct nlmsgerr *err = NLMSG_DATA(nlh);
+static int avc_netlink_process(char *buf)
+{
+ int rc;
+ struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
- /* Netlink ack */
- if (err->error == 0)
- break;
+ switch (nlh->nlmsg_type) {
+ case NLMSG_ERROR:{
+ struct nlmsgerr *err = NLMSG_DATA(nlh);
- errno = -err->error;
- avc_log("%s: netlink error: %d\n", avc_prefix,
- errno);
- rc = -1;
- goto out;
- }
+ /* Netlink ack */
+ if (err->error == 0)
+ break;
- case SELNL_MSG_SETENFORCE:{
- struct selnl_msg_setenforce *msg =
- NLMSG_DATA(nlh);
- avc_log
- ("%s: received setenforce notice (enforcing=%d)\n",
- avc_prefix, msg->val);
- avc_enforcing = msg->val;
- if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
- avc_log
- ("%s: cache reset returned %d (errno %d)\n",
- avc_prefix, rc, errno);
- goto out;
- }
- break;
- }
+ errno = -err->error;
+ avc_log("%s: netlink error: %d\n", avc_prefix, errno);
+ return -1;
+ }
- case SELNL_MSG_POLICYLOAD:{
- struct selnl_msg_policyload *msg =
- NLMSG_DATA(nlh);
- avc_log
- ("%s: received policyload notice (seqno=%d)\n",
- avc_prefix, msg->seqno);
- rc = avc_ss_reset(msg->seqno);
- if (rc < 0) {
- avc_log
- ("%s: cache reset returned %d (errno %d)\n",
- avc_prefix, rc, errno);
- goto out;
- }
- break;
- }
+ case SELNL_MSG_SETENFORCE:{
+ struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
+ avc_log("%s: received setenforce notice (enforcing=%d)\n",
+ avc_prefix, msg->val);
+ avc_enforcing = msg->val;
+ if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
+ avc_log("%s: cache reset returned %d (errno %d)\n",
+ avc_prefix, rc, errno);
+ return rc;
+ }
+ break;
+ }
- default:
- avc_log("%s: warning: unknown netlink message %d\n",
- avc_prefix, nlh->nlmsg_type);
+ case SELNL_MSG_POLICYLOAD:{
+ struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
+ avc_log("%s: received policyload notice (seqno=%d)\n",
+ avc_prefix, msg->seqno);
+ rc = avc_ss_reset(msg->seqno);
+ if (rc < 0) {
+ avc_log("%s: cache reset returned %d (errno %d)\n",
+ avc_prefix, rc, errno);
+ return rc; } + break; }
- out:
- return rc;
+
+ default:
+ avc_log("%s: warning: unknown netlink message %d\n",
+ avc_prefix, nlh->nlmsg_type);
+ }
+ return 0;
}
-/* run routine for the netlink listening thread */ -void avc_netlink_loop(void)
+int avc_netlink_check_nb(void)
{
- int ret;
- struct sockaddr_nl nladdr;
- socklen_t nladdrlen = sizeof nladdr;
+ int rc; char buf[1024];
- struct nlmsghdr *nlh;
while (1) {- ret =
- recvfrom(fd, buf, sizeof(buf), 0,
- (struct sockaddr *)&nladdr, &nladdrlen);
- if (ret < 0) {
- if (errno == EINTR)
+ errno = 0;
+ rc = avc_netlink_receive(buf, sizeof(buf));
+ if (rc < 0) {
+ if (errno == EWOULDBLOCK)
+ return 0;
+ if (errno == 0 || errno == EINTR)
continue;
- avc_log("%s: netlink thread: recvfrom: error %d\n",
- avc_prefix, errno);
- goto out;
+ else {
+ avc_log("%s: netlink recvfrom: error %d\n",
+ avc_prefix, errno);
+ return rc;
+ }
}
- if (nladdrlen != sizeof nladdr) {
- avc_log
- ("%s: warning: netlink address truncated, len %d?\n",
- avc_prefix, nladdrlen);
- ret = -1;
- goto out;
- }
+ (void)avc_netlink_process(buf);
+ }
+ return 0;
+}
- if (nladdr.nl_pid) {
- avc_log
- ("%s: warning: received spoofed netlink packet from: %d\n",
- avc_prefix, nladdr.nl_pid);
- continue;
- }
+/* run routine for the netlink listening thread */ +void avc_netlink_loop(void)
+{
+ int rc;
+ char buf[1024];
- if (ret == 0) {
- avc_log("%s: netlink thread: received EOF on socket\n",
- avc_prefix);
- goto out;
- }
-
- nlh = (struct nlmsghdr *)buf;
-
- if (nlh->nlmsg_flags & MSG_TRUNC
- || nlh->nlmsg_len > (unsigned)ret) {
- avc_log
- ("%s: netlink thread: incomplete netlink message\n",
- avc_prefix);
- goto out;
- }
-
- switch (nlh->nlmsg_type) {
- case NLMSG_ERROR:{
- struct nlmsgerr *err = NLMSG_DATA(nlh);
-
- /* Netlink ack */
- if (err->error == 0)
- break;
-
- avc_log("%s: netlink thread: msg: error %d\n",
- avc_prefix, -err->error);
- goto out;
- }
-
- case SELNL_MSG_SETENFORCE:{
- struct selnl_msg_setenforce *msg =
- NLMSG_DATA(nlh);
- avc_log
- ("%s: received setenforce notice (enforcing=%d)\n",
- avc_prefix, msg->val);
- avc_enforcing = msg->val;
- if (avc_enforcing && (ret = avc_ss_reset(0)) < 0) {
- avc_log
- ("%s: cache reset returned %d (errno %d)\n",
- avc_prefix, ret, errno);
- goto out;
- }
+ while (1) {
+ errno = 0;
+ rc = avc_netlink_receive(buf, sizeof(buf));
+ if (rc < 0) {
+ if (errno == 0 || errno == EINTR)
+ continue;
+ else {
+ avc_log("%s: netlink recvfrom: error %d\n",
+ avc_prefix, errno); break; }
-
- case SELNL_MSG_POLICYLOAD:{
- struct selnl_msg_policyload *msg =
- NLMSG_DATA(nlh);
- avc_log
- ("%s: received policyload notice (seqno=%d)\n",
- avc_prefix, msg->seqno);
- ret = avc_ss_reset(msg->seqno);
- if (ret < 0) {
- avc_log
- ("%s: netlink thread: cache reset returned %d (errno %d)\n",
- avc_prefix, ret, errno);
- goto out;
- }
- break;
- }
-
- default:
- avc_log
- ("%s: netlink thread: warning: unknown msg type %d\n",
- avc_prefix, nlh->nlmsg_type);
}
+
+ rc = avc_netlink_process(buf);
+ if (rc < 0)
+ break;
}
- out:
+
close(fd);
avc_netlink_trouble = 1;
avc_log("%s: netlink thread: errors encountered, terminating\n",Signature · 8 lines
Eamon Walsh <[email protected]> National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Quoted 9 lines · Eamon Walsh
This patch removes duplication in the AVC netlink code by introducing helper functions.
Did some basic testing and confirmed that messages are received and processed.
More patches to follow.
Signed-off-by Eamon Walsh <[email protected]>
Merged.
However, it occurs to me that this code may yield unaligned accesses (before and after this patch), just like the libsepol policy reading code until recently.
Quoted 340 lines
---
avc_internal.c | 289 +++++++++++++++++++++------------------------------------ 1 file changed, 107 insertions(+), 182 deletions(-)Index:
libselinux/src/avc_internal.c
===================================================================src/avc_internal.c +107
-182@@ -89,221 +89,146 @@close (fd); } -int avc_netlink_check_nb (void ) +static int avc_netlink_receive (char *buf,unsigned buflen) {int rc;struct sockaddr_nl nladdr;socklen_t nladdrlen =sizeof nladdr; -char buf[1024 ]; -struct nlmsghdr *nlh; +struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -while (1 ) { - rc =recvfrom (fd, buf,sizeof (buf),0 , - (struct sockaddr *)&nladdr, &nladdrlen); -if (rc <0 ) { -if (errno ==EINTR ) -continue ; -if (errno !=EAGAIN ) { -avc_log ("%s: socket error during read: %d\n" , - avc_prefix, errno); - }else { - errno =0 ; - rc =0 ; - } - goto out; - } + rc =recvfrom (fd, buf, buflen,0 , (struct sockaddr *)&nladdr, + &nladdrlen); +if (rc <0 ) +return rc; -if (nladdrlen !=sizeof nladdr) { -avc_log - ("%s: warning: netlink address truncated, len %d?\n" , - avc_prefix, nladdrlen); - rc =-1 ; - goto out; - } +if (nladdrlen !=sizeof nladdr) { +avc_log ("%s: warning: netlink address truncated, len %d?\n" , + avc_prefix, nladdrlen); +return -1 ; + } -if (nladdr.nl_pid) { -avc_log - ("%s: warning: received spoofed netlink packet from: %d\n" , - avc_prefix, nladdr.nl_pid); -continue ; - } +if (nladdr.nl_pid) { +avc_log ("%s: warning: received spoofed netlink packet from: %d\n" , + avc_prefix, nladdr.nl_pid); +return -1 ; + } -if (rc ==0 ) { -avc_log ("%s: warning: received EOF on socket\n" , - avc_prefix); - goto out; - } +if (rc ==0 ) { +avc_log ("%s: warning: received EOF on netlink socket\n" , + avc_prefix); + errno =EBADFD ; +return -1 ; + } - nlh = (struct nlmsghdr *)buf; +if (nlh->nlmsg_flags &MSG_TRUNC || nlh->nlmsg_len > (unsigned )rc) { +avc_log ("%s: warning: incomplete netlink message\n" , + avc_prefix); +return -1 ; + } -if (nlh->nlmsg_flags &MSG_TRUNC - || nlh->nlmsg_len > (unsigned )rc) { -avc_log ("%s: warning: incomplete netlink message\n" , - avc_prefix); - goto out; - } +return 0 ; +} - rc =0 ; -switch (nlh->nlmsg_type) { -case NLMSG_ERROR :{ -struct nlmsgerr *err =NLMSG_DATA (nlh); +static int avc_netlink_process (char *buf) +{ +int rc; +struct nlmsghdr *nlh = (struct nlmsghdr *)buf; -/* Netlink ack */ -if (err->error ==0 ) -break ; +switch (nlh->nlmsg_type) { +case NLMSG_ERROR :{ +struct nlmsgerr *err =NLMSG_DATA (nlh); - errno = -err->error; -avc_log ("%s: netlink error: %d\n" , avc_prefix, - errno); - rc =-1 ; - goto out; - } +/* Netlink ack */ +if (err->error ==0 ) +break ; -case SELNL_MSG_SETENFORCE :{ -struct selnl_msg_setenforce *msg = -NLMSG_DATA (nlh); -avc_log - ("%s: received setenforce notice (enforcing=%d)\n" , - avc_prefix, msg->val); - avc_enforcing = msg->val; -if (avc_enforcing && (rc =avc_ss_reset (0 )) <0 ) { -avc_log - ("%s: cache reset returned %d (errno %d)\n" , - avc_prefix, rc, errno); - goto out; - } -break ; - } + errno = -err->error; +avc_log ("%s: netlink error: %d\n" , avc_prefix, errno); +return -1 ; + } -case SELNL_MSG_POLICYLOAD :{ -struct selnl_msg_policyload *msg = -NLMSG_DATA (nlh); -avc_log - ("%s: received policyload notice (seqno=%d)\n" , - avc_prefix, msg->seqno); - rc =avc_ss_reset (msg->seqno); -if (rc <0 ) { -avc_log - ("%s: cache reset returned %d (errno %d)\n" , - avc_prefix, rc, errno); - goto out; - } -break ; - } +case SELNL_MSG_SETENFORCE :{ +struct selnl_msg_setenforce *msg =NLMSG_DATA (nlh); +avc_log ("%s: received setenforce notice (enforcing=%d)\n" , + avc_prefix, msg->val); + avc_enforcing = msg->val; +if (avc_enforcing && (rc =avc_ss_reset (0 )) <0 ) { +avc_log ("%s: cache reset returned %d (errno %d)\n" , + avc_prefix, rc, errno); +return rc; + } +break ; + } -default : -avc_log ("%s: warning: unknown netlink message %d\n" , - avc_prefix, nlh->nlmsg_type); +case SELNL_MSG_POLICYLOAD :{ +struct selnl_msg_policyload *msg =NLMSG_DATA (nlh); +avc_log ("%s: received policyload notice (seqno=%d)\n" , + avc_prefix, msg->seqno); + rc =avc_ss_reset (msg->seqno); +if (rc <0 ) { +avc_log ("%s: cache reset returned %d (errno %d)\n" , + avc_prefix, rc, errno); +return rc; } +break ; } - out: -return rc; + +default : +avc_log ("%s: warning: unknown netlink message %d\n" , + avc_prefix, nlh->nlmsg_type); + } +return 0 ; } -/* run routine for the netlink listening thread */ -void avc_netlink_loop (void ) +int avc_netlink_check_nb (void ) { -int ret; -struct sockaddr_nl nladdr; -socklen_t nladdrlen =sizeof nladdr; +int rc;char buf[1024 ]; -struct nlmsghdr *nlh;while (1 ) { - ret = -recvfrom (fd, buf,sizeof (buf),0 , - (struct sockaddr *)&nladdr, &nladdrlen); -if (ret <0 ) { -if (errno ==EINTR ) + errno =0 ; + rc =avc_netlink_receive (buf,sizeof (buf)); +if (rc <0 ) { +if (errno ==EWOULDBLOCK ) +return 0 ; +if (errno ==0 || errno ==EINTR )continue ; -avc_log ("%s: netlink thread: recvfrom: error %d\n" , - avc_prefix, errno); - goto out; +else { +avc_log ("%s: netlink recvfrom: error %d\n" , + avc_prefix, errno); +return rc; + } } -if (nladdrlen !=sizeof nladdr) { -avc_log - ("%s: warning: netlink address truncated, len %d?\n" , - avc_prefix, nladdrlen); - ret =-1 ; - goto out; - } + (void )avc_netlink_process (buf); + } +return 0 ; +} -if (nladdr.nl_pid) { -avc_log - ("%s: warning: received spoofed netlink packet from: %d\n" , - avc_prefix, nladdr.nl_pid); -continue ; - } +/* run routine for the netlink listening thread */ +void avc_netlink_loop (void ) +{ +int rc; +char buf[1024 ]; -if (ret ==0 ) { -avc_log ("%s: netlink thread: received EOF on socket\n" , - avc_prefix); - goto out; - } - - nlh = (struct nlmsghdr *)buf; - -if (nlh->nlmsg_flags &MSG_TRUNC - || nlh->nlmsg_len > (unsigned )ret) { -avc_log - ("%s: netlink thread: incomplete netlink message\n" , - avc_prefix); - goto out; - } - -switch (nlh->nlmsg_type) { -case NLMSG_ERROR :{ -struct nlmsgerr *err =NLMSG_DATA (nlh); - -/* Netlink ack */ -if (err->error ==0 ) -break ; - -avc_log ("%s: netlink thread: msg: error %d\n" , - avc_prefix, -err->error); - goto out; - } - -case SELNL_MSG_SETENFORCE :{ -struct selnl_msg_setenforce *msg = -NLMSG_DATA (nlh); -avc_log - ("%s: received setenforce notice (enforcing=%d)\n" , - avc_prefix, msg->val); - avc_enforcing = msg->val; -if (avc_enforcing && (ret =avc_ss_reset (0 )) <0 ) { -avc_log - ("%s: cache reset returned %d (errno %d)\n" , - avc_prefix, ret, errno); - goto out; - } +while (1 ) { + errno =0 ; + rc =avc_netlink_receive (buf,sizeof (buf)); +if (rc <0 ) { +if (errno ==0 || errno ==EINTR ) +continue ; +else { +avc_log ("%s: netlink recvfrom: error %d\n" , + avc_prefix, errno);break ; } - -case SELNL_MSG_POLICYLOAD :{ -struct selnl_msg_policyload *msg = -NLMSG_DATA (nlh); -avc_log - ("%s: received policyload notice (seqno=%d)\n" , - avc_prefix, msg->seqno); - ret =avc_ss_reset (msg->seqno); -if (ret <0 ) { -avc_log - ("%s: netlink thread: cache reset returned %d (errno %d)\n" , - avc_prefix, ret, errno); - goto out; - } -break ; - } - -default : -avc_log - ("%s: netlink thread: warning: unknown msg type %d\n" , - avc_prefix, nlh->nlmsg_type); } + + rc =avc_netlink_process (buf); +if (rc <0 ) +break ; } - out: +close (fd); avc_netlink_trouble =1 ; avc_log("%s: netlink thread: errors encountered, terminating\n",
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
PATCH 1/1 libselinux: introduce enforcing mode override option
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
---
include/selinux/avc.h | 11 ++++++++++- src/avc.c | 29 ++++++++++++++++++++--------- src/avc_internal.c | 7 +++++-- src/avc_internal.h | 1 + 4 files changed, 36 insertions(+), 12 deletions(-)
include/selinux/avc.h +0 -0
@@ -157,6 +157,15 @@
};
/*
+ * Available options
+ */
+
+/* no-op option, useful for unused slots in an array of options */
+#define AVC_OPT_UNUSED 0
+/* override kernel enforcing mode (boolean value) */
+#define AVC_OPT_SETENFORCE 1
+
+/*
* AVC operations
*/
@@ -188,7 +197,7 @@
*
* This function is identical to avc_init(), except the message prefix
* is set to "avc" and any callbacks desired should be specified via
- * selinux_set_callback(). No options are currently supported.
+ * selinux_set_callback(). Available options are listed above. */
int avc_open(struct selinux_opt *opts, unsigned nopts);
src/avc.c +0 -0
@@ -157,10 +157,19 @@
return rc; }
-int avc_open(struct selinux_opt *opts __attribute__((unused)),
- unsigned nopts __attribute__((unused)))
+int avc_open(struct selinux_opt *opts, unsigned nopts) {
- return avc_init("avc", NULL, NULL, NULL, NULL);
+ avc_setenforce = 0;
+
+ while (nopts--)
+ switch(opts[nopts].type) {
+ case AVC_OPT_SETENFORCE:
+ avc_setenforce = 1;
+ avc_enforcing = !!opts[nopts].value;
+ break;
+ }
+
+ return avc_init("avc", NULL, NULL, NULL, NULL);
}
int avc_init(const char *prefix,
@@ -213,13 +222,15 @@
avc_node_freelist = new; }
- rc = security_getenforce();
- if (rc < 0) {
- avc_log("%s: could not determine enforcing mode\n",
- avc_prefix);
- goto out;
+ if (!avc_setenforce) {
+ rc = security_getenforce();
+ if (rc < 0) {
+ avc_log("%s: could not determine enforcing mode\n",
+ avc_prefix);
+ goto out;
+ }
+ avc_enforcing = rc; }
- avc_enforcing = rc;
rc = avc_netlink_open(avc_using_threads);
if (rc < 0) {src/avc_internal.h +0 -0
@@ -74,6 +74,7 @@
extern char avc_prefix[AVC_PREFIX_SIZE] hidden;
extern int avc_running hidden;
extern int avc_enforcing hidden;
+extern int avc_setenforce hidden;
/* user-supplied callback interface for avc */
static inline void *avc_malloc(size_t size)
src/avc_internal.c +0 -0
@@ -46,6 +46,7 @@
char avc_prefix[AVC_PREFIX_SIZE] = "uavc";
int avc_running = 0;
int avc_enforcing = 1;
+int avc_setenforce = 0;
int avc_netlink_trouble = 0;
/* netlink socket code */
@@ -151,6 +152,8 @@
struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
avc_log("%s: received setenforce notice (enforcing=%d)\n",
avc_prefix, msg->val);
+ if (avc_setenforce)
+ break;
avc_enforcing = msg->val;
if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
avc_log("%s: cache reset returned %d (errno %d)\n",
@@ -183,7 +186,7 @@
int avc_netlink_check_nb(void)
{
int rc;- char buf[1024];
+ char buf[1024] __attribute__ ((aligned));
while (1) {
errno = 0;
@@ -209,7 +212,7 @@
void avc_netlink_loop(void)
{
int rc;- char buf[1024];
+ char buf[1024] __attribute__ ((aligned));
while (1) {
errno = 0;Signature · 8 lines
Eamon Walsh <[email protected]> National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH] libselinux: introduce enforcing mode override option
Quoted 3 lines · Eamon Walsh
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
I don't see a way for the object manager to change the enforcing status after avc_open().
attribute aligned diffs can be a separate patch.
Quoted 150 lines
Signed-off-by Eamon Walsh <[email protected]>---
include/selinux/avc.h | 11 ++++++++++- src/avc.c | 29 ++++++++++++++++++++--------- src/avc_internal.c | 7 +++++-- src/avc_internal.h | 1 + 4 files changed, 36 insertions(+), 12 deletions(-)Index:
libselinux/include/selinux/avc.h
===================================================================include/selinux/avc.h +10
-1@@ -157,6 +157,15 @@ };/* +* Available options +*/ + +/* no-op option, useful for unused slots in an array of options */ +#define AVC_OPT_UNUSED 0 +/* override kernel enforcing mode (boolean value) */ +#define AVC_OPT_SETENFORCE 1 + +/* * AVC operations */ @@ -188,7 +197,7 @@* * This function is identical to avc_init(), except the message prefix * is set to "avc" and any callbacks desired should be specified via -* selinux_set_callback(). No options are currently supported. +* selinux_set_callback(). Available options are listed above. */ int avc_open (struct selinux_opt *opts,unsigned nopts);Index:
libselinux/src/avc.c
===================================================================src/avc.c +20
-9@@ -157,10 +157,19 @@return rc; } -int avc_open (struct selinux_opt *opts __attribute__((unused)), -unsigned nopts __attribute__((unused))) +int avc_open (struct selinux_opt *opts,unsigned nopts) { -return avc_init ("avc" ,NULL ,NULL ,NULL ,NULL ); + avc_setenforce =0 ; + +while (nopts--) +switch (opts[nopts].type) { +case AVC_OPT_SETENFORCE : + avc_setenforce =1 ; + avc_enforcing = !!opts[nopts].value; +break ; + } + +return avc_init ("avc" ,NULL ,NULL ,NULL ,NULL ); } int avc_init(const char *prefix,@@ -213,13 +222,15 @@ avc_node_freelist = new; } - rc =security_getenforce (); -if (rc <0 ) { -avc_log ("%s: could not determine enforcing mode\n" , - avc_prefix); - goto out; +if (!avc_setenforce) { + rc =security_getenforce (); +if (rc <0 ) { +avc_log ("%s: could not determine enforcing mode\n" , + avc_prefix); + goto out; + } + avc_enforcing = rc; } - avc_enforcing = rc; rc =avc_netlink_open (avc_using_threads);if (rc <0 ) {Index:
libselinux/src/avc_internal.h
===================================================================src/avc_internal.h +1
-0@@ -74,6 +74,7 @@ extern char avc_prefix[AVC_PREFIX_SIZE] hidden; extern int avc_running hidden; extern int avc_enforcing hidden; +extern int avc_setenforce hidden;/* user-supplied callback interface for avc */ static inline void *avc_malloc (size_t size)Index:
libselinux/src/avc_internal.c
===================================================================src/avc_internal.c +5
-2@@ -46,6 +46,7 @@char avc_prefix[AVC_PREFIX_SIZE ] ="uavc" ;int avc_running =0 ;int avc_enforcing =1 ; +int avc_setenforce =0 ;int avc_netlink_trouble =0 ;/* netlink socket code */ @@ -151,6 +152,8 @@struct selnl_msg_setenforce *msg =NLMSG_DATA (nlh);avc_log ("%s: received setenforce notice (enforcing=%d)\n" , avc_prefix, msg->val); +if (avc_setenforce) +break ; avc_enforcing = msg->val;if (avc_enforcing && (rc =avc_ss_reset (0 )) <0 ) { avc_log("%s: cache reset returned %d (errno %d)\n",@@ -183,7 +186,7 @@int avc_netlink_check_nb (void ) {int rc; -char buf[1024 ]; + char buf[1024] __attribute__ ((aligned));while (1 ) { errno =0 ;@@ -209,7 +212,7 @@void avc_netlink_loop (void ) {int rc; -char buf[1024 ]; + char buf[1024] __attribute__ ((aligned));while (1 ) { errno =0 ;Signature · 9 lines
-- Eamon Walsh <[email protected]> National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH] libselinux: introduce enforcing mode override option
Quoted 10 lines · Smalley
Quoted 4 lines · Eamon Walsh
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
I don't see a way for the object manager to change the enforcing status after
avc_open().
I didn't think to include that. Do we want it? If so it can be added later.
Quoted 3 lines
attribute aligned diffs can be a separate patch.
I committed those two lines already. Rebased patch below.
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
---
include/selinux/avc.h | 11 ++++++++++- src/avc.c | 29 ++++++++++++++++++++--------- src/avc_internal.c | 3 +++ src/avc_internal.h | 1 + 4 files changed, 34 insertions(+), 10 deletions(-)
selinux/avc.h +0 -0
@@ -157,6 +157,15 @@
};
/*
+ * Available options
+ */
+
+/* no-op option, useful for unused slots in an array of options */
+#define AVC_OPT_UNUSED 0
+/* override kernel enforcing mode (boolean value) */
+#define AVC_OPT_SETENFORCE 1
+
+/*
* AVC operations
*/
@@ -188,7 +197,7 @@
*
* This function is identical to avc_init(), except the message prefix
* is set to "avc" and any callbacks desired should be specified via
- * selinux_set_callback(). No options are currently supported.
+ * selinux_set_callback(). Available options are listed above. */
int avc_open(struct selinux_opt *opts, unsigned nopts);
avc.c +0 -0
@@ -157,10 +157,19 @@
return rc; }
-int avc_open(struct selinux_opt *opts __attribute__((unused)),
- unsigned nopts __attribute__((unused)))
+int avc_open(struct selinux_opt *opts, unsigned nopts) {
- return avc_init("avc", NULL, NULL, NULL, NULL);
+ avc_setenforce = 0;
+
+ while (nopts--)
+ switch(opts[nopts].type) {
+ case AVC_OPT_SETENFORCE:
+ avc_setenforce = 1;
+ avc_enforcing = !!opts[nopts].value;
+ break;
+ }
+
+ return avc_init("avc", NULL, NULL, NULL, NULL);
}
int avc_init(const char *prefix,
@@ -213,13 +222,15 @@
avc_node_freelist = new; }
- rc = security_getenforce();
- if (rc < 0) {
- avc_log("%s: could not determine enforcing mode\n",
- avc_prefix);
- goto out;
+ if (!avc_setenforce) {
+ rc = security_getenforce();
+ if (rc < 0) {
+ avc_log("%s: could not determine enforcing mode\n",
+ avc_prefix);
+ goto out;
+ }
+ avc_enforcing = rc; }
- avc_enforcing = rc;
rc = avc_netlink_open(avc_using_threads);
if (rc < 0) {avc_internal.c +0 -0
@@ -46,6 +46,7 @@
char avc_prefix[AVC_PREFIX_SIZE] = "uavc";
int avc_running = 0;
int avc_enforcing = 1;
+int avc_setenforce = 0;
int avc_netlink_trouble = 0;
/* netlink socket code */
@@ -151,6 +152,8 @@
struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
avc_log("%s: received setenforce notice (enforcing=%d)\n",
avc_prefix, msg->val);
+ if (avc_setenforce)
+ break;
avc_enforcing = msg->val;
if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
avc_log("%s: cache reset returned %d (errno %d)\n",avc_internal.h +0 -0
@@ -74,6 +74,7 @@
extern char avc_prefix[AVC_PREFIX_SIZE] hidden;
extern int avc_running hidden;
extern int avc_enforcing hidden;
+extern int avc_setenforce hidden;
/* user-supplied callback interface for avc */
static inline void *avc_malloc(size_t size)
Signature · 8 lines
Eamon Walsh <[email protected]> National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Stephen Smalley
Acked-byRe: [PATCH] libselinux: introduce enforcing mode override option
Quoted 8 lines · Eamon Walsh
Quoted 7 lines · Smalley
Quoted 4 lines · Eamon Walsh
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
Quoted 6 lines
Quoted 3 lines
I don't see a way for the object manager to change the enforcing status after
avc_open().I didn't think to include that. Do we want it? If so it can be added later.
Ultimately, yes - I can envision a userspace object manager exporting its own interface for changing enforcing mode much as the kernel does, so admins can do "setenforce [kernel|x|postgres|dbus|...] [0|1]" or the like.
Quoted 5 lines
Quoted 4 lines
attribute aligned diffs can be a separate patch.
Quoted 7 lines
I committed those two lines already. Rebased patch below.
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
Signed-off-by Eamon Walsh <[email protected]>
Merge at will.
Quoted 126 lines
---
include/selinux/avc.h | 11 ++++++++++- src/avc.c | 29 ++++++++++++++++++++--------- src/avc_internal.c | 3 +++ src/avc_internal.h | 1 + 4 files changed, 34 insertions(+), 10 deletions(-)Index:
include/selinux/avc.h
===================================================================selinux/avc.h +10
-1@@ -157,6 +157,15 @@ };/* +* Available options +*/ + +/* no-op option, useful for unused slots in an array of options */ +#define AVC_OPT_UNUSED 0 +/* override kernel enforcing mode (boolean value) */ +#define AVC_OPT_SETENFORCE 1 + +/* * AVC operations */ @@ -188,7 +197,7 @@* * This function is identical to avc_init(), except the message prefix * is set to "avc" and any callbacks desired should be specified via -* selinux_set_callback(). No options are currently supported. +* selinux_set_callback(). Available options are listed above. */ int avc_open (struct selinux_opt *opts,unsigned nopts);Index:
src/avc.c
===================================================================avc.c +20
-9@@ -157,10 +157,19 @@return rc; } -int avc_open (struct selinux_opt *opts __attribute__((unused)), -unsigned nopts __attribute__((unused))) +int avc_open (struct selinux_opt *opts,unsigned nopts) { -return avc_init ("avc" ,NULL ,NULL ,NULL ,NULL ); + avc_setenforce =0 ; + +while (nopts--) +switch (opts[nopts].type) { +case AVC_OPT_SETENFORCE : + avc_setenforce =1 ; + avc_enforcing = !!opts[nopts].value; +break ; + } + +return avc_init ("avc" ,NULL ,NULL ,NULL ,NULL ); } int avc_init(const char *prefix,@@ -213,13 +222,15 @@ avc_node_freelist = new; } - rc =security_getenforce (); -if (rc <0 ) { -avc_log ("%s: could not determine enforcing mode\n" , - avc_prefix); - goto out; +if (!avc_setenforce) { + rc =security_getenforce (); +if (rc <0 ) { +avc_log ("%s: could not determine enforcing mode\n" , + avc_prefix); + goto out; + } + avc_enforcing = rc; } - avc_enforcing = rc; rc =avc_netlink_open (avc_using_threads);if (rc <0 ) {Index:
src/avc_internal.c
===================================================================avc_internal.c +3
-0@@ -46,6 +46,7 @@char avc_prefix[AVC_PREFIX_SIZE ] ="uavc" ;int avc_running =0 ;int avc_enforcing =1 ; +int avc_setenforce =0 ;int avc_netlink_trouble =0 ;/* netlink socket code */ @@ -151,6 +152,8 @@struct selnl_msg_setenforce *msg =NLMSG_DATA (nlh);avc_log ("%s: received setenforce notice (enforcing=%d)\n" , avc_prefix, msg->val); +if (avc_setenforce) +break ; avc_enforcing = msg->val;if (avc_enforcing && (rc =avc_ss_reset (0 )) <0 ) { avc_log("%s: cache reset returned %d (errno %d)\n",Index:
src/avc_internal.h
===================================================================avc_internal.h +1
-0@@ -74,6 +74,7 @@ extern char avc_prefix[AVC_PREFIX_SIZE] hidden; extern int avc_running hidden; extern int avc_enforcing hidden; +extern int avc_setenforce hidden;/* user-supplied callback interface for avc */ static inline void *avc_malloc (size_t size)Signature · 3 lines
-- Eamon Walsh <[email protected]> National Security Agency
Signature · 8 lines
Stephen Smalley National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH] libselinux: introduce enforcing mode override option
In reply to Eamon WalshQuoted 4 lines · Eamon Walsh
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
This is probably more useful but we actually had something like this with the userspace security server where you could run the USS in permissive or enforcing independent of the kernel security server. Ofcourse this would mean its still a global setting across all access managers using the USS.
Quoted 132 lines
Signed-off-by Eamon Walsh <[email protected]>---
include/selinux/avc.h | 11 ++++++++++- src/avc.c | 29 ++++++++++++++++++++--------- src/avc_internal.c | 7 +++++-- src/avc_internal.h | 1 + 4 files changed, 36 insertions(+), 12 deletions(-)Index:
libselinux/include/selinux/avc.h
===================================================================include/selinux/avc.h (working copy) renamed from include/selinux/avc.h (revision 2671) +10
-1@@ -157,6 +157,15 @@ }; /* + * Available options + */ + +/* no-op option, useful for unused slots in an array of options */ +#define AVC_OPT_UNUSED 0 +/* override kernel enforcing mode (boolean value) */ +#define AVC_OPT_SETENFORCE 1 + +/* * AVC operations */@@ -188,7 +197,7 @@ * * This function is identical to avc_init(), except the message prefix * is set to "avc" and any callbacks desired should be specified via - * selinux_set_callback(). No options are currently supported. + * selinux_set_callback(). Available options are listed above. */ int avc_open(struct selinux_opt *opts, unsigned nopts);Index:
libselinux/src/avc.c
===================================================================src/avc.c (working copy) renamed from src/avc.c (revision 2671) +20
-9@@ -157,10 +157,19 @@ return rc; } -int avc_open(struct selinux_opt *opts __attribute__((unused)), - unsigned nopts __attribute__((unused))) +int avc_open(struct selinux_opt *opts, unsigned nopts) { - return avc_init("avc", NULL, NULL, NULL, NULL); + avc_setenforce = 0; + + while (nopts--) + switch(opts[nopts].type) { + case AVC_OPT_SETENFORCE: + avc_setenforce = 1; + avc_enforcing = !!opts[nopts].value; + break; + } + + return avc_init("avc", NULL, NULL, NULL, NULL); } int avc_init(const char *prefix,@@ -213,13 +222,15 @@ avc_node_freelist = new; } - rc = security_getenforce(); - if (rc < 0) { - avc_log("%s: could not determine enforcing mode\n", - avc_prefix); - goto out; + if (!avc_setenforce) { + rc = security_getenforce(); + if (rc < 0) { + avc_log("%s: could not determine enforcing mode\n", + avc_prefix); + goto out; + } + avc_enforcing = rc; } - avc_enforcing = rc; rc = avc_netlink_open(avc_using_threads); if (rc < 0) {Index:
libselinux/src/avc_internal.h
===================================================================src/avc_internal.h (working copy) renamed from src/avc_internal.h (revision 2671) +1
-0@@ -74,6 +74,7 @@ extern char avc_prefix[AVC_PREFIX_SIZE] hidden; extern int avc_running hidden; extern int avc_enforcing hidden; +extern int avc_setenforce hidden; /* user-supplied callback interface for avc */ static inline void *avc_malloc(size_t size)Index:
libselinux/src/avc_internal.c
===================================================================src/avc_internal.c (working copy) renamed from src/avc_internal.c (revision 2671) +4
-1@@ -46,6 +46,7 @@ char avc_prefix[AVC_PREFIX_SIZE] = "uavc"; int avc_running = 0; int avc_enforcing = 1; +int avc_setenforce = 0; int avc_netlink_trouble = 0; /* netlink socket code */@@ -151,6 +152,8 @@ struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh); avc_log("%s: received setenforce notice (enforcing=%d)\n", avc_prefix, msg->val); + if (avc_setenforce) + break; avc_enforcing = msg->val; if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) { avc_log("%s: cache reset returned %d (errno %d)\n",@@ -183,7 +186,7 @@ int avc_netlink_check_nb(void) { int rc; - char buf[1024]; + char buf[1024] __attribute__ ((aligned)); while (1) { errno = 0;
src/avc_internal.c (working copy) line 218
Quoted 8 lines
src/avc_internal.c (working copy) renamed from src/avc_internal.c (revision 2671) +1
-1@@ -209,7 +212,7 @@ void avc_netlink_loop(void) { int rc; - char buf[1024]; + char buf[1024] __attribute__ ((aligned)); while (1) { errno = 0;
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH] libselinux: introduce enforcing mode override option
Quoted 8 lines · Joshua Brindle
Quoted 4 lines · Eamon Walsh
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
This is probably more useful but we actually had something like this with the userspace security server where you could run the USS in permissive or enforcing independent of the kernel security server. Ofcourse this would mean its still a global setting across all access managers using the USS.
Interesting, I would think that the USS would only serve up "raw" decisions like the kernel security server does. The permissive setting is a construct of the AVC layer.
Signature · 7 lines
Eamon Walsh <[email protected]> National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.
Re: [PATCH] libselinux: introduce enforcing mode override option
Quoted 11 lines · Eamon Walsh
Quoted 8 lines · Joshua Brindle
Quoted 4 lines · Eamon Walsh
Introduces an enforcing mode override option, so the object manager can bring up the AVC in permissive mode on an enforcing system, or vice versa.
This is probably more useful but we actually had something like this with the userspace security server where you could run the USS in permissive or enforcing independent of the kernel security server. Ofcourse this would mean its still a global setting across all access managers using the USS.
Interesting, I would think that the USS would only serve up "raw" decisions like the kernel security server does. The permissive setting is a construct of the AVC layer.
The avc gets the enforcing mode from the security server, in this case the USS was delivering its own enforcing mode independent of the kss.
--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.