diff --git a/libselinux/include/selinux/avc.h b/libselinux/include/selinux/avc.h index 1ea25a2d..9ec23abb 100644 --- a/libselinux/include/selinux/avc.h +++ b/libselinux/include/selinux/avc.h @@ -427,6 +427,21 @@ void avc_av_stats(void); */ void avc_sid_stats(void); +/** + * avc_netlink_open - Create a netlink socket and connect to the kernel. + */ +int avc_netlink_open(int blocking); + +/** + * avc_netlink_loop - Wait for netlink messages from the kernel + */ +void avc_netlink_loop(void); + +/** + * avc_netlink_close - Close the netlink socket + */ +void avc_netlink_close(void); + /** * avc_netlink_acquire_fd - Acquire netlink socket fd. * diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h index fab083e3..73f5db03 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -153,11 +153,17 @@ __attribute__ ((format(printf, 2, 3))) char *msgbuf, size_t msgbufsize); /* validate the supplied context, modifying if necessary */ int (*func_validate) (security_context_t *ctx); + /* netlink callback for setenforce message */ + int (*func_setenforce) (int enforcing); + /* netlink callback for policyload message */ + int (*func_policyload) (int seqno); }; #define SELINUX_CB_LOG 0 #define SELINUX_CB_AUDIT 1 #define SELINUX_CB_VALIDATE 2 +#define SELINUX_CB_SETENFORCE 3 +#define SELINUX_CB_POLICYLOAD 4 extern union selinux_callback selinux_get_callback(int type); extern void selinux_set_callback(int type, union selinux_callback cb); diff --git a/libselinux/man/man3/avc_netlink_acquire_fd.3 b/libselinux/man/man3/avc_netlink_acquire_fd.3 new file mode 100644 index 00000000..293a9473 --- /dev/null +++ b/libselinux/man/man3/avc_netlink_acquire_fd.3 @@ -0,0 +1 @@ +.so man3/avc_netlink_loop.3 diff --git a/libselinux/man/man3/avc_netlink_check_nb.3 b/libselinux/man/man3/avc_netlink_check_nb.3 new file mode 100644 index 00000000..293a9473 --- /dev/null +++ b/libselinux/man/man3/avc_netlink_check_nb.3 @@ -0,0 +1 @@ +.so man3/avc_netlink_loop.3 diff --git a/libselinux/man/man3/avc_netlink_close.3 b/libselinux/man/man3/avc_netlink_close.3 new file mode 100644 index 00000000..293a9473 --- /dev/null +++ b/libselinux/man/man3/avc_netlink_close.3 @@ -0,0 +1 @@ +.so man3/avc_netlink_loop.3 diff --git a/libselinux/man/man3/avc_netlink_loop.3 b/libselinux/man/man3/avc_netlink_loop.3 new file mode 100644 index 00000000..67df6e46 --- /dev/null +++ b/libselinux/man/man3/avc_netlink_loop.3 @@ -0,0 +1,88 @@ +.\" Hey Emacs! This file is -*- nroff -*- source. +.\" +.\" Author: KaiGai Kohei (kaigai@ak.jp.nec.com) 2009 +.TH "avc_netlink_loop" "3" "30 Mar 2009" "" "SELinux API documentation" +.SH "NAME" +avc_netlink_open, avc_netlink_close, avc_netlink_acquire_fd, +avc_netlink_release_fd, avc_netlink_check_nb, avc_netlink_loop \- SELinux +netlink processing. +.SH "SYNOPSIS" +.B #include + +.B #include +.sp +.BI "int avc_netlink_open(int " blocking ");" +.sp +.BI "void avc_netlink_close(void);" +.sp +.BI "int avc_netlink_acquire_fd(void);" +.sp +.BI "void avc_netlink_release_fd(void);" +.sp +.BI "void avc_netlink_loop(void);" +.sp +.BI "int avc_netlink_check_nb(void);" +.sp +.SH "DESCRIPTION" +These functions enable applications to handle notification of SELinux events +via netlink. The userspace AVC normally checks for netlink messages on each +call to +.BR avc_has_perm (3). +Applications may wish to override this behavior and check for notification +separately, for example in a +.BR select (2) +loop. These functions also permit netlink monitoring without requiring a +call to +.BR avc_open (3). + +.B avc_netlink_open +opens a netlink socket to receive SELinux notifications. The socket +descriptor is stored internally; use +.BR avc_netlink_acquire_fd (3) +to take ownership of it in application code. The +.I blocking +argument specifies whether read operations on the socket will block. +.BR avc_open (3) +calls this function internally, specifying non-blocking behavior (unless +threading callbacks were explicitly set using the deprecated +.BR avc_init (3) +interface, in which case blocking behavior is set). + +.B avc_netlink_close +closes the netlink socket. This function is called automatically by +.BR avc_destroy (3). + +.B avc_netlink_acquire_fd +returns the netlink socket descriptor number and informs the userspace AVC +not to check the socket descriptor automatically on calls to +.BR avc_has_perm (3). + +.B avc_netlink_release_fd +returns control of the netlink socket to the userspace AVC, re-enabling +automatic processing of notifications. + +.B avc_netlink_check_nb +checks the netlink socket for pending messages and processes them. +Callbacks for policyload and enforcing changes will be called; +see +.BR selinux_set_callback (3). +This function does not block unless +.BR avc_netlink_open (3) +specified blocking behavior. + +.B avc_netlink_loop +enters a loop blocking on the netlink socket and processing messages as they +are received. This function will not return unless an error occurs on +the socket, in which case the socket is closed. + +.SH "RETURN VALUE" +.B avc_netlink_acquire_fd +returns a non-negative file descriptor number on success. Other functions +with a return value return zero on success. On error, -1 is returned and +.I errno +is set appropriately. + +.SH "SEE ALSO" +.BR avc_open (3), +.BR selinux_set_callback (3), +.BR selinux (8) diff --git a/libselinux/man/man3/avc_netlink_open.3 b/libselinux/man/man3/avc_netlink_open.3 new file mode 100644 index 00000000..293a9473 --- /dev/null +++ b/libselinux/man/man3/avc_netlink_open.3 @@ -0,0 +1 @@ +.so man3/avc_netlink_loop.3 diff --git a/libselinux/man/man3/avc_netlink_release_fd.3 b/libselinux/man/man3/avc_netlink_release_fd.3 new file mode 100644 index 00000000..293a9473 --- /dev/null +++ b/libselinux/man/man3/avc_netlink_release_fd.3 @@ -0,0 +1 @@ +.so man3/avc_netlink_loop.3 diff --git a/libselinux/man/man3/selinux_set_callback.3 b/libselinux/man/man3/selinux_set_callback.3 index 6d6a7234..4f8d74de 100644 --- a/libselinux/man/man3/selinux_set_callback.3 +++ b/libselinux/man/man3/selinux_set_callback.3 @@ -79,6 +79,28 @@ should be set to .B EINVAL to indicate an invalid context. +.TP +.B SELINUX_CB_SETENFORCE +.BI "int (*" func_setenforce ") (int " enforcing ");" + +This callback is invoked when the system enforcing state changes. +The +.I enforcing +argument indicates the new value and is set to +.I 1 +for enforcing mode, and +.I 0 +for permissive mode. + +.TP +.B SELINUX_CB_POLICYLOAD +.BI "int (*" func_policyload ") (int " seqno ");" + +This callback is invoked when the system security policy is reloaded. +The +.I seqno +argument is the current sequential number of the policy generation in the system. + .SH "RETURN VALUE" None. @@ -91,5 +113,6 @@ Eamon Walsh .SH "SEE ALSO" .BR selabel_open (3), .BR avc_init (3), +.BR avc_netlink_open(3), .BR selinux (8) diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c index 7d6f33de..8372f522 100644 --- a/libselinux/src/avc_internal.c +++ b/libselinux/src/avc_internal.c @@ -19,6 +19,7 @@ #include #include #include +#include "callbacks.h" #include "selinux_netlink.h" #include "avc_internal.h" @@ -168,6 +169,9 @@ static int avc_netlink_process(char *buf) avc_prefix, rc, errno); return rc; } + rc = selinux_netlink_setenforce(msg->val); + if (rc < 0) + return rc; break; } @@ -183,6 +187,9 @@ static int avc_netlink_process(char *buf) avc_prefix, rc, errno); return rc; } + rc = selinux_netlink_policyload(msg->seqno); + if (rc < 0) + return rc; break; } diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h index 986ea7ce..e9e57721 100644 --- a/libselinux/src/avc_internal.h +++ b/libselinux/src/avc_internal.h @@ -184,9 +184,6 @@ int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid, /* netlink kernel message code */ extern int avc_netlink_trouble hidden; -int avc_netlink_open(int blocking) hidden; -void avc_netlink_loop(void) hidden; -void avc_netlink_close(void) hidden; hidden_proto(avc_av_stats) hidden_proto(avc_cleanup) diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c index 5acfd3d1..b245364c 100644 --- a/libselinux/src/callbacks.c +++ b/libselinux/src/callbacks.c @@ -37,6 +37,18 @@ default_selinux_validate(security_context_t *ctx) return security_check_context(*ctx); } +static int +default_selinux_setenforce(int enforcing __attribute__((unused))) +{ + return 0; +} + +static int +default_selinux_policyload(int seqno __attribute__((unused))) +{ + return 0; +} + /* callback pointers */ int __attribute__ ((format(printf, 2, 3))) (*selinux_log)(int, const char *, ...) = @@ -50,6 +62,14 @@ int (*selinux_validate)(security_context_t *ctx) = default_selinux_validate; +int +(*selinux_netlink_setenforce) (int enforcing) = + default_selinux_setenforce; + +int +(*selinux_netlink_policyload) (int seqno) = + default_selinux_policyload; + /* callback setting function */ void selinux_set_callback(int type, union selinux_callback cb) @@ -64,6 +84,12 @@ selinux_set_callback(int type, union selinux_callback cb) case SELINUX_CB_VALIDATE: selinux_validate = cb.func_validate; break; + case SELINUX_CB_SETENFORCE: + selinux_netlink_setenforce = cb.func_setenforce; + break; + case SELINUX_CB_POLICYLOAD: + selinux_netlink_policyload = cb.func_policyload; + break; } } @@ -83,6 +109,12 @@ selinux_get_callback(int type) case SELINUX_CB_VALIDATE: cb.func_validate = selinux_validate; break; + case SELINUX_CB_SETENFORCE: + cb.func_setenforce = selinux_netlink_setenforce; + break; + case SELINUX_CB_POLICYLOAD: + cb.func_policyload = selinux_netlink_policyload; + break; default: memset(&cb, 0, sizeof(cb)); errno = EINVAL; diff --git a/libselinux/src/callbacks.h b/libselinux/src/callbacks.h index 068fa9df..52ad5550 100644 --- a/libselinux/src/callbacks.h +++ b/libselinux/src/callbacks.h @@ -21,4 +21,10 @@ extern int extern int (*selinux_validate)(security_context_t *ctx) hidden; +extern int +(*selinux_netlink_setenforce) (int enforcing) hidden; + +extern int +(*selinux_netlink_policyload) (int seqno) hidden; + #endif /* _SELINUX_CALLBACKS_H_ */