libselinux: minor updates to AVC, mapping, callbacks
PATCH 1/3 libselinux: minor updates to AVC, mapping, callbacks
This patch introduces the selinux_get_callback() companion to selinux_set_callback() that was discussed on-list recently.
Added a format attribute to the callback union definition to squash a gcc warning.
---
include/selinux/selinux.h | 4 +++-src/callbacks.c | 25 +++++++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
include/selinux/selinux.h +0 -0
@@ -142,7 +142,8 @@
union selinux_callback {
/* log the printf-style format and arguments,
with the type code indicating the type of message */- int (*func_log) (int type, const char *fmt, ...);
+ int __attribute__((format(printf, 2, 3)))
+ (*func_log) (int type, const char *fmt, ...);
/* store a string representation of auditdata (corresponding
to the given security class) into msgbuf. */
int (*func_audit) (void *auditdata, security_class_t cls,
@@ -155,6 +156,7 @@
#define SELINUX_CB_AUDIT 1
#define SELINUX_CB_VALIDATE 2
+extern union selinux_callback selinux_get_callback(int type); extern void selinux_set_callback(int type, union selinux_callback cb);
/* Logging type codes, passed to the logging callback */
src/callbacks.c +0 -0
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <errno.h>
#include <selinux/selinux.h>
#include "callbacks.h"
@@ -65,3 +66,27 @@
break; } }
+
+/* callback getting function */
+union selinux_callback
+selinux_get_callback(int type)
+{
+ union selinux_callback cb;
+
+ switch (type) {
+ case SELINUX_CB_LOG:
+ cb.func_log = selinux_log;
+ break;
+ case SELINUX_CB_AUDIT:
+ cb.func_audit = selinux_audit;
+ break;
+ case SELINUX_CB_VALIDATE:
+ cb.func_validate = selinux_validate;
+ break;
+ default:
+ memset(&cb, 0, sizeof(cb));
+ errno = EINVAL;
+ break;
+ }
+ return cb;
+}
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.
PATCH 2/3 libselinux: minor updates to AVC, mapping, callbacks
This patch introduces a replacement for avc_init(), avc_open(). The purpose of this is to move away from the callbacks specified to avc_init() and instead set callbacks with selinux_set_callback(), as well as to use the same option mechanism as selabel_open().
Also updated the old avc_init callbacks to call the new ones if they are set.
---
include/selinux/avc.h | 11 +++++++++++ src/avc.c | 6 ++++++ src/avc_internal.h | 5 ++++- 3 files changed, 21 insertions(+), 1 deletion(-)
include/selinux/avc.h +0 -0
@@ -182,6 +182,17 @@
const struct avc_lock_callback *lock_callbacks);
/**
+ * avc_open - Initialize the AVC.
+ * @opts: array of selabel_opt structures specifying AVC options or NULL.
+ * @nopts: number of elements in opts array or zero for no options.
+ *
+ * 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.
+ */
+int avc_open(struct selinux_opt *opts, unsigned nopts);
+
+/**
* avc_cleanup - Remove unused SIDs and AVC entries.
*
* Search the SID table for SID structures with zero
src/avc.c +0 -0
@@ -157,6 +157,12 @@
return rc; }
+int avc_open(struct selinux_opt *opts __attribute__((unused)),
+ unsigned nopts __attribute__((unused)))
+{
+ return avc_init("avc", NULL, NULL, NULL, NULL);
+}
+
int avc_init(const char *prefix,
const struct avc_memory_callback *mem_cb, const struct avc_log_callback *log_cb,
src/avc_internal.h +0 -0
@@ -13,6 +13,7 @@
#include <stdlib.h>
#include <string.h>
#include <selinux/avc.h>
+#include "callbacks.h"
#include "dso.h"
/* SID reference counter manipulation */
@@ -93,13 +94,15 @@
if (avc_func_log) \
avc_func_log(format); \ else \
- fprintf(stderr, format)
+ selinux_log(SELINUX_ERROR, format);
static inline void avc_suppl_audit(void *ptr, security_class_t class,
char *buf, size_t len)
{
if (avc_func_audit)
avc_func_audit(ptr, class, buf, len);+ else
+ selinux_audit(ptr, class, buf, len);
}
static inline void *avc_create_thread(void (*run) (void))
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.
PATCH 3/3 libselinux: minor updates to AVC, mapping, callbacks
In reply to Eamon WalshThis patch allows empty strings to be specified as permissions in the dynamic permission mapping. An empty string will be interpreted as a "skipped bit" which allows userspace object managers to use non-contiguous permission bits.
---
mapping.c | 6 ++++++
1 file changed, 6 insertions(+)
src/mapping.c +0 -0
@@ -68,6 +68,11 @@
k = 0;
while (p_in->perms && p_in->perms[k]) {+ /* An empty permission string skips ahead */
+ if (!*p_in->perms[k]) {
+ k++;
+ continue;
+ }
p_out->perms[k] = string_to_av_perm(p_out->value, p_in->perms[k]); if (!p_out->perms[k])
@@ -111,6 +116,7 @@
for (i=0; i<current_mapping[tclass].num_perms; i++)
if (tperm & (1<<i)) {
+ assert(current_mapping[tclass].perms[i]);
kperm |= current_mapping[tclass].perms[i];
tperm &= ~(1<<i);
}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 5 lines · Eamon Walsh
This patch allows empty strings to be specified as permissions in the dynamic permission mapping. An empty string will be interpreted as a "skipped bit" which allows userspace object managers to use non-contiguous permission bits.
Why is this necessary?
Quoted 27 lines
Signed-off-by Eamon Walsh <[email protected]>---
mapping.c| 6 ++++++1 file changed, 6 insertions(+)Index:
libselinux/src/mapping.c
===================================================================src/mapping.c (working copy) renamed from src/mapping.c (revision 2628) +5
-0@@ -68,6 +68,11 @@ k = 0; while (p_in->perms && p_in->perms[k]) { + /* An empty permission string skips ahead */ + if (!*p_in->perms[k]) { + k++; + continue; + } p_out->perms[k] = string_to_av_perm(p_out->value, p_in->perms[k]); if (!p_out->perms[k])
src/mapping.c (working copy) line 122
Quoted 7 lines
src/mapping.c (working copy) renamed from src/mapping.c (revision 2628) +1
-0@@ -111,6 +116,7 @@ for (i=0; i<current_mapping[tclass].num_perms; i++) if (tperm & (1<<i)) { + assert(current_mapping[tclass].perms[i]); kperm |= current_mapping[tclass].perms[i]; tperm &= ~(1<<i); }
--
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 8 lines · Joshua Brindle
Quoted 5 lines · Eamon Walsh
This patch allows empty strings to be specified as permissions in the dynamic permission mapping. An empty string will be interpreted as a "skipped bit" which allows userspace object managers to use non-contiguous permission bits.
Why is this necessary?
In X there is only one hook function for each object type. The access mode being requested is passed as a bitfield of globally defined permission bits. This is a legacy of the SECURITY extension that existed before I started my work. The global permissions are pasted below FYI.
This patch allows me to define the Flask permission bits to be the same as these global bits and just pass them through. Without it, I'd have to remap the bits on each check.
If you think it's a bad solution, maybe we could go back to the original proposal for the mapping function which was to pass the desired class and permission values explicitly along with the strings.
#define DixUnknownAccess 0 /* don't know intentions */
#define DixReadAccess (1<<0) /* inspecting the object */
#define DixWriteAccess (1<<1) /* changing the object */
#define DixDestroyAccess (1<<2) /* destroying the object */
#define DixCreateAccess (1<<3) /* creating the object */
#define DixGetAttrAccess (1<<4) /* get object attributes */
#define DixSetAttrAccess (1<<5) /* set object attributes */
#define DixListPropAccess (1<<6) /* list properties of object */
#define DixGetPropAccess (1<<7) /* get properties of object */
#define DixSetPropAccess (1<<8) /* set properties of object */
#define DixGetFocusAccess (1<<9) /* get focus of object */
#define DixSetFocusAccess (1<<10) /* set focus of object */
#define DixListAccess (1<<11) /* list objects */
#define DixAddAccess (1<<12) /* add object */
#define DixRemoveAccess (1<<13) /* remove object */
#define DixHideAccess (1<<14) /* hide object */
#define DixShowAccess (1<<15) /* show object */
#define DixBlendAccess (1<<16) /* mix contents of objects */
#define DixGrabAccess (1<<17) /* exclusive access to object */
#define DixFreezeAccess (1<<18) /* freeze status of object */
#define DixForceAccess (1<<19) /* force status of object */
#define DixInstallAccess (1<<20) /* install object */
#define DixUninstallAccess (1<<21) /* uninstall object */
#define DixSendAccess (1<<22) /* send to object */
#define DixReceiveAccess (1<<23) /* receive from object */
#define DixUseAccess (1<<24) /* use object */
#define DixManageAccess (1<<25) /* manage object */
#define DixDebugAccess (1<<26) /* debug object */
#define DixBellAccess (1<<27) /* audible sound */
Quoted 37 lines
Quoted 35 lines
Signed-off-by Eamon Walsh <[email protected]>---
mapping.c| 6 ++++++1 file changed, 6 insertions(+)Index:
libselinux/src/mapping.c
===================================================================src/mapping.c (working copy) renamed from src/mapping.c (revision 2628) +6
-0@@ -68,6 +68,11 @@ k = 0; while (p_in->perms && p_in->perms[k]) { + /* An empty permission string skips ahead */ + if (!*p_in->perms[k]) { + k++; + continue; + } p_out->perms[k] = string_to_av_perm(p_out->value, p_in->perms[k]); if (!p_out->perms[k])@@ -111,6 +116,7 @@ for (i=0; i<current_mapping[tclass].num_perms; i++) if (tperm & (1<<i)) { + assert(current_mapping[tclass].perms[i]); kperm |= current_mapping[tclass].perms[i]; tperm &= ~(1<<i); }
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.
Quoted 6 lines · Eamon Walsh
This patch allows empty strings to be specified as permissions in the dynamic permission mapping. An empty string will be interpreted as a "skipped bit" which allows userspace object managers to use non-contiguous permission bits.
Signed-off-by Eamon Walsh <[email protected]>
Merged all three, although we can revisit the last one if you find a cleaner solution.
Quoted 33 lines
---
mapping.c | 6 ++++++ 1 file changed, 6 insertions(+)Index:
libselinux/src/mapping.c
===================================================================src/mapping.c +6
-0@@ -68,6 +68,11 @@ k =0 ;while (p_in->perms && p_in->perms[k]) { +/* An empty permission string skips ahead */ +if (!*p_in->perms[k]) { + k++; +continue ; + } p_out->perms[k] =string_to_av_perm (p_out->value, p_in->perms[k]);if (!p_out->perms[k])@@ -111,6 +116,7 @@for (i=0 ; i<current_mapping[tclass].num_perms; i++)if (tperm & (1 <<i)) { +assert (current_mapping[tclass].perms[i]); kperm |= current_mapping[tclass].perms[i]; tperm &= ~(1 <<i); }
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.