/**************************************************************** * acm_policy.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 policy management for Xen. * This interface allows policy tools in authorized * domains to interact with the Xen access control module * */ #include #include #include #include #include #include #include #include #include #include int acm_set_policy(void *buf, u32 buf_size, int isuserbuffer) { u8 *policy_buffer = NULL; struct acm_policy_buffer *pol; if (buf_size < sizeof(struct acm_policy_buffer)) return -EFAULT; /* 1. copy buffer from domain */ if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) return -ENOMEM; if (isuserbuffer) { if (copy_from_user(policy_buffer, buf, buf_size)) { printk("%s: Error copying!\n",__func__); goto error_free; } } else memcpy(policy_buffer, buf, buf_size); /* 2. some sanity checking */ pol = (struct acm_policy_buffer *)policy_buffer; if ((ntohl(pol->magic) != ACM_MAGIC) || (buf_size != ntohl(pol->len)) || (ntohl(pol->policy_version) != ACM_POLICY_VERSION)) { printk("%s: ERROR in Magic, Version, or buf size.\n", __func__); goto error_free; } if (acm_active_security_policy == ACM_POLICY_UNDEFINED) { /* setup the policy with the boot policy */ if (acm_init_binary_policy((ntohl(pol->secondary_policy_code) << 4) | ntohl(pol->primary_policy_code))) { goto error_free; } acm_active_security_policy = (acm_bin_pol.secondary_policy_code << 4) | acm_bin_pol.primary_policy_code; } /* once acm_active_security_policy is set, it cannot be changed */ if ((ntohl(pol->primary_policy_code) != acm_bin_pol.primary_policy_code) || (ntohl(pol->secondary_policy_code) != acm_bin_pol.secondary_policy_code)) { printkd("%s: Wrong policy type in boot policy!\n", __func__); goto error_free; } /* get bin_policy lock and rewrite policy (release old one) */ write_lock(&acm_bin_pol_rwlock); /* 3. set primary policy data */ if (acm_primary_ops->set_binary_policy(buf + ntohl(pol->primary_buffer_offset), ntohl(pol->secondary_buffer_offset) - ntohl(pol->primary_buffer_offset))) goto error_lock_free; /* 4. set secondary policy data */ if (acm_secondary_ops->set_binary_policy(buf + ntohl(pol->secondary_buffer_offset), ntohl(pol->len) - ntohl(pol->secondary_buffer_offset))) goto error_lock_free; write_unlock(&acm_bin_pol_rwlock); xfree(policy_buffer); return ACM_OK; error_lock_free: write_unlock(&acm_bin_pol_rwlock); error_free: printk("%s: Error setting policy.\n", __func__); xfree(policy_buffer); return -EFAULT; } int acm_get_policy(void *buf, u32 buf_size) { u8 *policy_buffer; int ret; struct acm_policy_buffer *bin_pol; if (buf_size < sizeof(struct acm_policy_buffer)) return -EFAULT; if ((policy_buffer = xmalloc_array(u8, buf_size)) == NULL) return -ENOMEM; read_lock(&acm_bin_pol_rwlock); bin_pol = (struct acm_policy_buffer *)policy_buffer; bin_pol->magic = htonl(ACM_MAGIC); bin_pol->primary_policy_code = htonl(acm_bin_pol.primary_policy_code); bin_pol->secondary_policy_code = htonl(acm_bin_pol.secondary_policy_code); bin_pol->len = htonl(sizeof(struct acm_policy_buffer)); bin_pol->primary_buffer_offset = htonl(ntohl(bin_pol->len)); bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len)); ret = acm_primary_ops->dump_binary_policy (policy_buffer + ntohl(bin_pol->primary_buffer_offset), buf_size - ntohl(bin_pol->primary_buffer_offset)); if (ret < 0) goto error_free_unlock; bin_pol->len = htonl(ntohl(bin_pol->len) + ret); bin_pol->secondary_buffer_offset = htonl(ntohl(bin_pol->len)); ret = acm_secondary_ops->dump_binary_policy(policy_buffer + ntohl(bin_pol->secondary_buffer_offset), buf_size - ntohl(bin_pol->secondary_buffer_offset)); if (ret < 0) goto error_free_unlock; bin_pol->len = htonl(ntohl(bin_pol->len) + ret); if (copy_to_user(buf, policy_buffer, ntohl(bin_pol->len))) goto error_free_unlock; read_unlock(&acm_bin_pol_rwlock); xfree(policy_buffer); return ACM_OK; error_free_unlock: read_unlock(&acm_bin_pol_rwlock); printk("%s: Error getting policy.\n", __func__); xfree(policy_buffer); return -EFAULT; } int acm_dump_statistics(void *buf, u16 buf_size) { /* send stats to user space */ u8 *stats_buffer; int len1, len2; struct acm_stats_buffer acm_stats; if ((stats_buffer = xmalloc_array(u8, buf_size)) == NULL) return -ENOMEM; read_lock(&acm_bin_pol_rwlock); len1 = acm_primary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer), buf_size - sizeof(struct acm_stats_buffer)); if (len1 < 0) goto error_lock_free; len2 = acm_secondary_ops->dump_statistics(stats_buffer + sizeof(struct acm_stats_buffer) + len1, buf_size - sizeof(struct acm_stats_buffer) - len1); if (len2 < 0) goto error_lock_free; acm_stats.magic = htonl(ACM_MAGIC); acm_stats.primary_policy_code = htonl(acm_bin_pol.primary_policy_code); acm_stats.secondary_policy_code = htonl(acm_bin_pol.secondary_policy_code); acm_stats.primary_stats_offset = htonl(sizeof(struct acm_stats_buffer)); acm_stats.secondary_stats_offset = htonl(sizeof(struct acm_stats_buffer) + len1); acm_stats.len = htonl(sizeof(struct acm_stats_buffer) + len1 + len2); memcpy(stats_buffer, &acm_stats, sizeof(struct acm_stats_buffer)); if (copy_to_user(buf, stats_buffer, sizeof(struct acm_stats_buffer) + len1 + len2)) goto error_lock_free; read_unlock(&acm_bin_pol_rwlock); xfree(stats_buffer); return ACM_OK; error_lock_free: read_unlock(&acm_bin_pol_rwlock); xfree(stats_buffer); return -EFAULT; } int acm_get_ssid(ssidref_t ssidref, u8 *buf, u16 buf_size) { /* send stats to user space */ u8 *ssid_buffer; int ret; struct acm_ssid_buffer *acm_ssid; if (buf_size < sizeof(struct acm_ssid_buffer)) return -EFAULT; if ((ssid_buffer = xmalloc_array(u8, buf_size)) == NULL) return -ENOMEM; read_lock(&acm_bin_pol_rwlock); acm_ssid = (struct acm_ssid_buffer *)ssid_buffer; acm_ssid->len = sizeof(struct acm_ssid_buffer); acm_ssid->ssidref = ssidref; acm_ssid->primary_policy_code = acm_bin_pol.primary_policy_code; acm_ssid->secondary_policy_code = acm_bin_pol.secondary_policy_code; acm_ssid->primary_types_offset = acm_ssid->len; /* ret >= 0 --> ret == max_types */ r
/*
 * lib/error.c		Error Handling
 *
 *	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) 2008 Thomas Graf <tgraf@suug.ch>
 */

#include <netlink-local.h>
#include <netlink/netlink.h>

static const char *errmsg[NLE_MAX+1] = {
[NLE_SUCCESS]		= "Success",
[NLE_FAILURE]		= "Unspecific failure",
[NLE_INTR]		= "Interrupted system call",
[NLE_BAD_SOCK]		= "Bad socket",
[NLE_AGAIN]		= "Try again",
[NLE_NOMEM]		= "Out of memory",
[NLE_EXIST]		= "Object exists",
[NLE_INVAL]		= "Invalid input data or parameter",
[NLE_RANGE]		= "Input data out of range",
[NLE_MSGSIZE]		= "Message size not sufficient",
[NLE_OPNOTSUPP]		= "Operation not supported",
[NLE_AF_NOSUPPORT]	= "Address family not supported",
[NLE_OBJ_NOTFOUND]	= "Object not found",
[NLE_NOATTR]		= "Attribute not available",
[NLE_MISSING_ATTR]	= "Missing attribute",
[NLE_AF_MISMATCH]	= "Address family mismatch",
[NLE_SEQ_MISMATCH]	= "Message sequence number mismatch",
[NLE_MSG_OVERFLOW]	= "Kernel reported message overflow",
[NLE_MSG_TRUNC]		= "Kernel reported truncated message",
[NLE_NOADDR]		= "Invalid address for specified address family",
[NLE_SRCRT_NOSUPPORT]	= "Source based routing not supported",
[NLE_MSG_TOOSHORT]	= "Netlink message is too short",
[NLE_MSGTYPE_NOSUPPORT]	= "Netlink message type is not supported",
[NLE_OBJ_MISMATCH]	= "Object type does not match cache",
[NLE_NOCACHE]		= "Unknown or invalid cache type",
[NLE_BUSY]		= "Object busy",
[NLE_PROTO_MISMATCH]	= "Protocol mismatch",
[NLE_NOACCESS]		= "No Access",
[NLE_PERM]		= "Operation not permitted",
[NLE_PKTLOC_FILE]	= "Unable to open packet location file",
[NLE_PARSE_ERR]		= "Unable to parse object",
[NLE_NODEV]		= "No such device",
[NLE_IMMUTABLE]		= "Immutable attribute",
[NLE_DUMP_INTR]		= "Dump inconsistency detected, interrupted",
};

/**
 * Return error message for an error code
 * @return error message
 */
const char *nl_geterror(int error)
{
	error = abs(error);

	if (error > NLE_MAX)
		error = NLE_FAILURE;

	return errmsg[error];
}

/**
 * Print a libnl error message
 * @arg s		error message prefix
 *
 * Prints the error message of the call that failed last.
 *
 * If s is not NULL and *s is not a null byte the argument
 * string is printed, followed by a colon and a blank. Then
 * the error message and a new-line.
 */
void nl_perror(int error, const char *s)
{
	if (s && *s)
		fprintf(stderr, "%s: %s\n", s, nl_geterror(error));
	else
		fprintf(stderr, "%s\n", nl_geterror(error));
}

int nl_syserr2nlerr(int error)
{
	error = abs(error);

	switch (error) {
	case EBADF:		return NLE_BAD_SOCK;
	case EADDRINUSE:	return NLE_EXIST;
	case EEXIST:		return NLE_EXIST;
	case EADDRNOTAVAIL:	return NLE_NOADDR;
	case ESRCH:		/* fall through */
	case ENOENT:		return NLE_OBJ_NOTFOUND;
	case EINTR:		return NLE_INTR;
	case EAGAIN:		return NLE_AGAIN;
	case ENOTSOCK:		return NLE_BAD_SOCK;
	case ENOPROTOOPT:	return NLE_INVAL;
	case EFAULT:		return NLE_INVAL;
	case EACCES:		return NLE_NOACCESS;
	case EINVAL:		return NLE_INVAL;
	case ENOBUFS:		return NLE_NOMEM;
	case ENOMEM:		return NLE_NOMEM;
	case EAFNOSUPPORT:	return NLE_AF_NOSUPPORT;
	case EPROTONOSUPPORT:	return NLE_PROTO_MISMATCH;
	case EOPNOTSUPP:	return NLE_OPNOTSUPP;
	case EPERM:		return NLE_PERM;
	case EBUSY:		return NLE_BUSY;
	case ERANGE:		return NLE_RANGE;
	case ENODEV:		return NLE_NODEV;
	default:		return NLE_FAILURE;
	}
}

/** @} */