/**************************************************************** * acm_core.c * * Copyright (C) 2005 IBM Corporation * * Author: * Reiner Sailer * * Contributors: * Stefan Berger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation, version 2 of the * License. * * sHype access control module (ACM) * This file handles initialization of the ACM * as well as initializing/freeing security * identifiers for domains (it calls on active * policy hook functions). * */ #include #include #include #include #include #include #include #include #include /* debug: * include/acm/acm_hooks.h defines a constant ACM_TRACE_MODE; * define/undefine this constant to receive / suppress any * security hook debug output of sHype * * include/public/acm.h defines a constant ACM_DEBUG * define/undefine this constant to receive non-hook-related * debug output. */ /* function prototypes */ void acm_init_chwall_policy(void); void acm_init_ste_policy(void); extern struct acm_operations acm_chinesewall_ops, acm_simple_type_enforcement_ops, acm_null_ops; /* global ACM policy (now dynamically determined at boot time) */ u16 acm_active_security_policy = ACM_POLICY_UNDEFINED; /* global ops structs called by the hooks */ struct acm_operations *acm_primary_ops = NULL; /* called in hook if-and-only-if primary succeeds */ struct acm_operations *acm_secondary_ops = NULL; /* acm global binary policy (points to 'local' primary and secondary policies */ struct acm_binary_policy acm_bin_pol; /* acm binary policy lock */ rwlock_t acm_bin_pol_rwlock = RW_LOCK_UNLOCKED; /* until we have endian support in Xen, we discover it at runtime */ u8 little_endian = 1; void acm_set_endian(void) { u32 test = 1; if (*((u8 *)&test) == 1) { printkd("ACM module running in LITTLE ENDIAN.\n"); little_endian = 1; } else { printkd("ACM module running in BIG ENDIAN.\n"); little_endian = 0; } } int acm_set_policy_reference(u8 * buf, u32 buf_size) { struct acm_policy_reference_buffer *pr = (struct acm_policy_reference_buffer *)buf; acm_bin_pol.policy_reference_name = (char *)xmalloc_array(u8, ntohl(pr->len)); if (!acm_bin_pol.policy_reference_name) return -ENOMEM; strcpy(acm_bin_pol.policy_reference_name, (char *)(buf + sizeof(struct acm_policy_reference_buffer))); printk("%s: Activating policy %s\n", __func__, acm_bin_pol.policy_reference_name); return 0; } int acm_dump_policy_reference(u8 *buf, u32 buf_size) { struct acm_policy_reference_buffer *pr_buf = (struct acm_policy_reference_buffer *)buf; int ret = sizeof(struct acm_policy_reference_buffer) + strlen(acm_bin_pol.policy_reference_name) + 1; if (buf_size < ret) return -EINVAL; pr_buf->len = htonl(strlen(acm_bin_pol.policy_reference_name) + 1); /* including stringend '\0' */ strcpy((char *)(buf + sizeof(struct acm_policy_reference_buffer)), acm_bin_pol.policy_reference_name); return ret; } int acm_init_binary_policy(u32 policy_code) { int ret = ACM_OK; acm_bin_pol.primary_policy_code = (policy_code & 0x0f); acm_bin_pol.secondary_policy_code = (policy_code >> 4) & 0x0f; write_lock(&acm_bin_pol_rwlock); /* set primary policy component */ switch ((policy_code) & 0x0f) { case ACM_CHINESE_WALL_POLICY: acm_init_chwall_policy(); acm_bin_pol.primary_policy_code = ACM_CHINESE_WALL_POLICY; acm_primary_ops = &acm_chinesewall_ops; break; case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: acm_init_ste_policy(); acm_bin_pol.primary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; acm_primary_ops = &acm_simple_type_enforcement_ops; break; case ACM_NULL_POLICY: acm_bin_pol.primary_policy_code = ACM_NULL_POLICY; acm_primary_ops = &acm_null_ops; break; default: /* Unknown policy not allowed primary */ ret = -EINVAL; goto out; } /* secondary policy component part */ switch ((policy_code) >> 4) { case ACM_NULL_POLICY: acm_bin_pol.secondary_policy_code = ACM_NULL_POLICY; acm_secondary_ops = &acm_null_ops; break; case ACM_CHINESE_WALL_POLICY: if (acm_bin_pol.primary_policy_code == ACM_CHINESE_WALL_POLICY) { /* not a valid combination */ ret = -EINVAL; goto out; } acm_init_chwall_policy(); acm_bin_pol.secondary_policy_code = ACM_CHINESE_WALL_POLICY; acm_secondary_ops = &acm_chinesewall_ops; break; case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY: if (acm_bin_pol.primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) { /* not a valid combination */ ret = -EINVAL; goto out; } acm_init_ste_policy(); acm_bin_pol.secondary_policy_code = ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY; acm_secondary_ops = &acm_simple_type_enforcement_ops; break; default: ret = -EINVAL; goto out; } out: write_unlock(&acm_bin_pol_rwlock); return ret; } static int acm_setup(unsigned int *initrdidx, const multiboot_info_t *mbi, unsigned long initial_images_start) { int i; module_t *mod = (module_t *)__va(mbi->mods_addr); int rc = ACM_OK; if (mbi->mods_count > 1) *initrdidx = 1; /* * Try all modules and see whichever could be the binary policy. * Adjust the initrdidx if module[1] is the binary policy. */ for (i = mbi->mods_count-1; i >= 1; i--) { struct acm_policy_buffer *pol; char *_policy_start; unsigned long _policy_len; #if defined(__i386__) _policy_start = (char *)(initial_images_start + (mod[i].mod_start-mod[0].mod_start)); #elif defined(__x86_64__) _policy_start = __va(initial_images_start + (mod[i].mod_start-mod[0].mod_start)); #else #error Architecture unsupported by sHype #endif _policy_len = mod[i].mod_end - mod[i].mod_start; if (_policy_len < sizeof(struct acm_policy_buffer)) continue; /* not a policy */ pol = (struct acm_policy_buffer *)_policy_start; if (ntohl(pol->magic) == ACM_MAGIC) { rc = do_acm_set_policy((void *)_policy_start, (u32)_policy_len); if (rc == ACM_OK) { printkd("Policy len 0x%lx, start at %p.\n",_policy_len,_policy_start); if (i == 1) { if (mbi->mods_count > 2) { *initrdidx = 2; } else { *initrdidx = 0; } } else { *initrdidx = 1; } break; } else { printk("Invalid policy. %d.th module line.\n", i+1); /* load default policy later */ acm_active_security_policy = ACM_POLICY_UNDEFINED; } } /* end if a binary policy definition, i.e., (ntohl(pol->magic) == ACM_MAGIC ) */ } return rc; } int acm_init(unsigned int *initrdidx, const multiboot_info_t *mbi, unsigned long initial_images_start) { int ret = ACM_OK; acm_set_endian(); /* first try to load the boot policy (uses its own locks) */ acm_setup(initrdidx, mbi, initial_images_start); if (acm_active_security_policy != ACM_POLICY_UNDEFINED) { printk("%s: Enforcing %s boot policy.\n", __func__, ACM_POLICY_NAME(acm_active_security_policy)); goto out; } /* else continue with the minimal hardcoded default startup policy */ printk("%s: Loading default policy (%s).\n", __func__, ACM_POLICY_NAME(ACM_DEFAULT_SECURITY_POLICY)); if (acm_init_binary_policy(ACM_DEFAULT_SECURITY_POLICY)) { ret = -EINVAL; goto out; } acm_active_security_policy = ACM_DEFAULT_SECURITY_POLICY; if (acm_active_security_policy != ACM_NULL_POLICY) acm_bin_pol.p
/*
 * netlink/cache.h		Caching Module
 *
 *	This library is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU Lesser General Public
 *	License as published by the Free Software Foundation version 2.1
 *	of the License.
 *
 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
 */

#ifndef NETLINK_CACHE_H_
#define NETLINK_CACHE_H_

#include <netlink/netlink.h>
#include <netlink/msg.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/cache-api.h>

#ifdef __cplusplus
extern "C" {
#endif

struct nl_cache;

typedef void (*change_func_t)(struct nl_cache *, struct nl_object *, int);

/* Access Functions */
extern int			nl_cache_nitems(struct nl_cache *);
extern int			nl_cache_nitems_filter(struct nl_cache *,
						       struct nl_object *);
extern struct nl_cache_ops *	nl_cache_get_ops(struct nl_cache *);
extern struct nl_object *	nl_cache_get_first(struct nl_cache *);
extern struct nl_object *	nl_cache_get_last(struct nl_cache *);
extern struct nl_object *	nl_cache_get_next(struct nl_object *);
extern struct nl_object *	nl_cache_get_prev(struct nl_object *);

extern struct nl_cache *	nl_cache_alloc(struct nl_cache_ops *);
extern int			nl_cache_alloc_and_fill(struct nl_cache_ops *,
							struct nl_sock *,
							struct nl_cache **);
extern int			nl_cache_alloc_name(const char *,
						    struct nl_cache **);
extern struct nl_cache *	nl_cache_subset(struct nl_cache *,
						struct nl_object *);
extern void			nl_cache_clear(struct nl_cache *);
extern void			nl_cache_free(struct nl_cache *);

/* Cache modification */
extern int			nl_cache_add(struct nl_cache *,
					     struct nl_object *);
extern int			nl_cache_parse_and_add(struct nl_cache *,
						       struct nl_msg *);
extern void			nl_cache_remove(struct nl_object *);
extern int			nl_cache_refill(struct nl_sock *,
						struct nl_cache *);
extern int			nl_cache_pickup(struct nl_sock *,
						struct nl_cache *);
extern int			nl_cache_resync(struct nl_sock *,
						struct nl_cache *,
						change_func_t);
extern int			nl_cache_include(struct nl_cache *,
						 struct nl_object *,
						 change_func_t);

/* General */
extern int			nl_cache_is_empty(struct nl_cache *);
extern void			nl_cache_mark_all(struct nl_cache *);

/* Dumping */
extern void			nl_cache_dump(struct nl_cache *,
					      struct nl_dump_params *);
extern void			nl_cache_dump_filter(struct nl_cache *,
						     struct nl_dump_params *,
						     struct nl_object *);

/* Iterators */
#ifdef disabled
extern void			nl_cache_foreach(struct nl_cache *,
						 void (*cb)(struct nl_object *,
							    void *),
						 void *arg);
extern void			nl_cache_foreach_filter(struct nl_cache *,
							struct nl_object *,
							void (*cb)(struct
								   nl_object *,
								   void *),
							void *arg);
#endif

/* --- cache management --- */

/* Cache type management */
extern struct nl_cache_ops *	nl_cache_ops_lookup(const char *);
extern struct nl_cache_ops *	nl_cache_ops_associate(int, int);
extern struct nl_msgtype *	nl_msgtype_lookup(struct nl_cache_ops *, int);
extern void			nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *);
extern int			nl_cache_mngt_register(struct nl_cache_ops *);
extern int			nl_cache_mngt_unregister(struct nl_cache_ops *);

/* Global cache provisioning/requiring */
extern void			nl_cache_mngt_provide(struct nl_cache *);
extern void			nl_cache_mngt_unprovide(struct nl_cache *);
extern struct nl_cache *	nl_cache_mngt_require(const char *);

struct nl_cache_mngr;

#define NL_AUTO_PROVIDE		1

extern int			nl_cache_mngr_alloc(struct nl_sock *,
						    int, int,
						    struct nl_cache_mngr **);
extern int			nl_cache_mngr_add(struct nl_cache_mngr *,
						  const char *,
						  change_func_t,
						  struct nl_cache **);
extern int			nl_cache_mngr_get_fd(struct nl_cache_mngr *);
extern int			nl_cache_mngr_poll(struct nl_cache_mngr *,
						   int);
extern int			nl_cache_mngr_data_ready(struct nl_cache_mngr *);
extern void			nl_cache_mngr_free(struct nl_cache_mngr *);

#ifdef __cplusplus
}
#endif

#endif