The attached patch enables userspace object managers to handle notification
messages via netlink socket from SELinux. * Two new callbacks were added to selinux_set_callback(3) - SELINUX_CB_SETENFORCE is invoked when it got SELNL_MSG_SETENFORCE message in the avc_netlink_process(). - SELINUX_CB_POLICYLOAD is invoked when it got SELNL_MSG_POLICYLOAD message in the avc_netlink_process(). * Three functions were exposed to applications. - int avc_netlink_open(int blocking); - void avc_netlink_loop(void); - void avc_netlink_close(void); Due to a few reasons, SE-PostgreSQL implements its own userspace avc, so it needs to copy and paste some of avc_internal.c. This update enables to share common part from such kind of application. Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
This commit is contained in:
parent
4d98bd7e52
commit
318748d659
13 changed files with 182 additions and 3 deletions
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
1
libselinux/man/man3/avc_netlink_acquire_fd.3
Normal file
1
libselinux/man/man3/avc_netlink_acquire_fd.3
Normal file
|
@ -0,0 +1 @@
|
|||
.so man3/avc_netlink_loop.3
|
1
libselinux/man/man3/avc_netlink_check_nb.3
Normal file
1
libselinux/man/man3/avc_netlink_check_nb.3
Normal file
|
@ -0,0 +1 @@
|
|||
.so man3/avc_netlink_loop.3
|
1
libselinux/man/man3/avc_netlink_close.3
Normal file
1
libselinux/man/man3/avc_netlink_close.3
Normal file
|
@ -0,0 +1 @@
|
|||
.so man3/avc_netlink_loop.3
|
88
libselinux/man/man3/avc_netlink_loop.3
Normal file
88
libselinux/man/man3/avc_netlink_loop.3
Normal file
|
@ -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 <selinux/selinux.h>
|
||||
|
||||
.B #include <selinux/avc.h>
|
||||
.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)
|
1
libselinux/man/man3/avc_netlink_open.3
Normal file
1
libselinux/man/man3/avc_netlink_open.3
Normal file
|
@ -0,0 +1 @@
|
|||
.so man3/avc_netlink_loop.3
|
1
libselinux/man/man3/avc_netlink_release_fd.3
Normal file
1
libselinux/man/man3/avc_netlink_release_fd.3
Normal file
|
@ -0,0 +1 @@
|
|||
.so man3/avc_netlink_loop.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 <ewalsh@tycho.nsa.gov>
|
|||
.SH "SEE ALSO"
|
||||
.BR selabel_open (3),
|
||||
.BR avc_init (3),
|
||||
.BR avc_netlink_open(3),
|
||||
.BR selinux (8)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <sys/socket.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in a new issue