* Security hooks for XFRM operations.
*
* @xfrm_policy_alloc_security:
- * @xp contains the xfrm_policy being added to Security Policy Database
- * used by the XFRM system.
+ * @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
+ * Database used by the XFRM system.
* @sec_ctx contains the security context information being provided by
* the user-level policy update program (e.g., setkey).
* Allocate a security structure to the xp->security field; the security
* field is initialized to NULL when the xfrm_policy is allocated.
* Return 0 if operation was successful (memory to allocate, legal context)
* @xfrm_policy_clone_security:
- * @old contains an existing xfrm_policy in the SPD.
- * @new contains a new xfrm_policy being cloned from old.
- * Allocate a security structure to the new->security field
- * that contains the information from the old->security field.
+ * @old_ctx contains an existing xfrm_sec_ctx.
+ * @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
+ * Allocate a security structure in new_ctxp that contains the
+ * information from the old_ctx structure.
* Return 0 if operation was successful (memory to allocate).
* @xfrm_policy_free_security:
- * @xp contains the xfrm_policy
+ * @ctx contains the xfrm_sec_ctx
* Deallocate xp->security.
* @xfrm_policy_delete_security:
- * @xp contains the xfrm_policy.
+ * @ctx contains the xfrm_sec_ctx.
* Authorize deletion of xp->security.
* @xfrm_state_alloc_security:
* @x contains the xfrm_state being added to the Security Association
* @x contains the xfrm_state.
* Authorize deletion of x->security.
* @xfrm_policy_lookup:
- * @xp contains the xfrm_policy for which the access control is being
+ * @ctx contains the xfrm_sec_ctx for which the access control is being
* checked.
* @fl_secid contains the flow security label that is used to authorize
* access to the policy xp.
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
- int (*xfrm_policy_alloc_security) (struct xfrm_policy *xp,
+ int (*xfrm_policy_alloc_security) (struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx);
- int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new);
- void (*xfrm_policy_free_security) (struct xfrm_policy *xp);
- int (*xfrm_policy_delete_security) (struct xfrm_policy *xp);
+ int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
+ void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
+ int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
int (*xfrm_state_alloc_security) (struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx,
u32 secid);
void (*xfrm_state_free_security) (struct xfrm_state *x);
int (*xfrm_state_delete_security) (struct xfrm_state *x);
- int (*xfrm_policy_lookup)(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
+ int (*xfrm_policy_lookup)(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl);
int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
#ifdef CONFIG_SECURITY_NETWORK_XFRM
-int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
-int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
-void security_xfrm_policy_free(struct xfrm_policy *xp);
-int security_xfrm_policy_delete(struct xfrm_policy *xp);
+int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx);
+int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp);
+void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
+int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid);
int security_xfrm_state_delete(struct xfrm_state *x);
void security_xfrm_state_free(struct xfrm_state *x);
-int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
+int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl);
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
#else /* CONFIG_SECURITY_NETWORK_XFRM */
-static inline int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
+static inline int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
{
return 0;
}
-static inline int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+static inline int security_xfrm_policy_clone(struct xfrm_sec_ctx *old, struct xfrm_sec_ctx **new_ctxp)
{
return 0;
}
-static inline void security_xfrm_policy_free(struct xfrm_policy *xp)
+static inline void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
}
-static inline int security_xfrm_policy_delete(struct xfrm_policy *xp)
+static inline int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
return 0;
}
return 0;
}
-static inline int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
+static inline int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
return 0;
}
goto out;
}
- err = security_xfrm_policy_alloc(xp, uctx);
+ err = security_xfrm_policy_alloc(&xp->security, uctx);
kfree(uctx);
if (err)
int err;
struct sadb_address *sa;
struct sadb_x_policy *pol;
- struct xfrm_policy *xp, tmp;
+ struct xfrm_policy *xp;
struct xfrm_selector sel;
struct km_event c;
struct sadb_x_sec_ctx *sec_ctx;
+ struct xfrm_sec_ctx *pol_ctx;
if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
sel.dport_mask = htons(0xffff);
sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1];
- memset(&tmp, 0, sizeof(struct xfrm_policy));
-
if (sec_ctx != NULL) {
struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
if (!uctx)
return -ENOMEM;
- err = security_xfrm_policy_alloc(&tmp, uctx);
+ err = security_xfrm_policy_alloc(&pol_ctx, uctx);
kfree(uctx);
-
if (err)
return err;
- }
-
- xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
- &sel, tmp.security, 1, &err);
- security_xfrm_policy_free(&tmp);
+ } else
+ pol_ctx = NULL;
+ xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN,
+ pol->sadb_x_policy_dir - 1, &sel, pol_ctx,
+ 1, &err);
+ security_xfrm_policy_free(pol_ctx);
if (xp == NULL)
return -ENOENT;
if ((*dir = verify_sec_ctx_len(p)))
goto out;
uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
- *dir = security_xfrm_policy_alloc(xp, uctx);
+ *dir = security_xfrm_policy_alloc(&xp->security, uctx);
kfree(uctx);
if (*dir)
list_del(&policy->bytype);
write_unlock_bh(&xfrm_policy_lock);
- security_xfrm_policy_free(policy);
+ security_xfrm_policy_free(policy->security);
kfree(policy);
}
EXPORT_SYMBOL(xfrm_policy_destroy);
xfrm_sec_ctx_match(ctx, pol->security)) {
xfrm_pol_hold(pol);
if (delete) {
- *err = security_xfrm_policy_delete(pol);
+ *err = security_xfrm_policy_delete(
+ pol->security);
if (*err) {
write_unlock_bh(&xfrm_policy_lock);
return pol;
if (pol->type == type && pol->index == id) {
xfrm_pol_hold(pol);
if (delete) {
- *err = security_xfrm_policy_delete(pol);
+ *err = security_xfrm_policy_delete(
+ pol->security);
if (*err) {
write_unlock_bh(&xfrm_policy_lock);
return pol;
&xfrm_policy_inexact[dir], bydst) {
if (pol->type != type)
continue;
- err = security_xfrm_policy_delete(pol);
+ err = security_xfrm_policy_delete(pol->security);
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
bydst) {
if (pol->type != type)
continue;
- err = security_xfrm_policy_delete(pol);
+ err = security_xfrm_policy_delete(
+ pol->security);
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
match = xfrm_selector_match(sel, fl, family);
if (match)
- ret = security_xfrm_policy_lookup(pol, fl->secid, dir);
+ ret = security_xfrm_policy_lookup(pol->security, fl->secid,
+ dir);
return ret;
}
int err = 0;
if (match) {
- err = security_xfrm_policy_lookup(pol, fl->secid,
- policy_to_flow_dir(dir));
+ err = security_xfrm_policy_lookup(pol->security,
+ fl->secid,
+ policy_to_flow_dir(dir));
if (!err)
xfrm_pol_hold(pol);
else if (err == -ESRCH)
if (newp) {
newp->selector = old->selector;
- if (security_xfrm_policy_clone(old, newp)) {
+ if (security_xfrm_policy_clone(old->security,
+ &newp->security)) {
kfree(newp);
return NULL; /* ENOMEM */
}
return 0;
uctx = nla_data(rt);
- return security_xfrm_policy_alloc(pol, uctx);
+ return security_xfrm_policy_alloc(&pol->security, uctx);
}
static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
NETLINK_CB(skb).sid);
if (err) {
- security_xfrm_policy_free(xp);
+ security_xfrm_policy_free(xp->security);
kfree(xp);
return err;
}
xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
- struct xfrm_policy tmp;
+ struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs);
if (err)
return err;
- memset(&tmp, 0, sizeof(struct xfrm_policy));
if (rt) {
struct xfrm_user_sec_ctx *uctx = nla_data(rt);
- if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
+ err = security_xfrm_policy_alloc(&ctx, uctx);
+ if (err)
return err;
- }
- xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
+ } else
+ ctx = NULL;
+ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx,
delete, &err);
- security_xfrm_policy_free(&tmp);
+ security_xfrm_policy_free(ctx);
}
if (xp == NULL)
return -ENOENT;
xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX];
- struct xfrm_policy tmp;
+ struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs);
if (err)
return err;
- memset(&tmp, 0, sizeof(struct xfrm_policy));
if (rt) {
struct xfrm_user_sec_ctx *uctx = nla_data(rt);
- if ((err = security_xfrm_policy_alloc(&tmp, uctx)))
+ err = security_xfrm_policy_alloc(&ctx, uctx);
+ if (err)
return err;
- }
- xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security,
- 0, &err);
- security_xfrm_policy_free(&tmp);
+ } else
+ ctx = NULL;
+ xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err);
+ security_xfrm_policy_free(ctx);
}
-
if (xp == NULL)
return -ENOENT;
+
read_lock(&xp->lock);
if (xp->dead) {
read_unlock(&xp->lock);
#endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM
-static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *sec_ctx)
+static int dummy_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
+ struct xfrm_user_sec_ctx *sec_ctx)
{
return 0;
}
-static inline int dummy_xfrm_policy_clone_security(struct xfrm_policy *old, struct xfrm_policy *new)
+static inline int dummy_xfrm_policy_clone_security(struct xfrm_sec_ctx *old_ctx,
+ struct xfrm_sec_ctx **new_ctxp)
{
return 0;
}
-static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
+static void dummy_xfrm_policy_free_security(struct xfrm_sec_ctx *ctx)
{
}
-static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
+static int dummy_xfrm_policy_delete_security(struct xfrm_sec_ctx *ctx)
{
return 0;
}
return 0;
}
-static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
+static int dummy_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx,
+ u32 sk_sid, u8 dir)
{
return 0;
}
#ifdef CONFIG_SECURITY_NETWORK_XFRM
-int security_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx)
+int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx)
{
- return security_ops->xfrm_policy_alloc_security(xp, sec_ctx);
+ return security_ops->xfrm_policy_alloc_security(ctxp, sec_ctx);
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);
-int security_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
+ struct xfrm_sec_ctx **new_ctxp)
{
- return security_ops->xfrm_policy_clone_security(old, new);
+ return security_ops->xfrm_policy_clone_security(old_ctx, new_ctxp);
}
-void security_xfrm_policy_free(struct xfrm_policy *xp)
+void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
- security_ops->xfrm_policy_free_security(xp);
+ security_ops->xfrm_policy_free_security(ctx);
}
EXPORT_SYMBOL(security_xfrm_policy_free);
-int security_xfrm_policy_delete(struct xfrm_policy *xp)
+int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
- return security_ops->xfrm_policy_delete_security(xp);
+ return security_ops->xfrm_policy_delete_security(ctx);
}
int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
security_ops->xfrm_state_free_security(x);
}
-int security_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
+int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
- return security_ops->xfrm_policy_lookup(xp, fl_secid, dir);
+ return security_ops->xfrm_policy_lookup(ctx, fl_secid, dir);
}
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
#ifndef _SELINUX_XFRM_H_
#define _SELINUX_XFRM_H_
-int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *sec_ctx);
-int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
-void selinux_xfrm_policy_free(struct xfrm_policy *xp);
-int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
+int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
+ struct xfrm_user_sec_ctx *sec_ctx);
+int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
+ struct xfrm_sec_ctx **new_ctxp);
+void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
+int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx);
int selinux_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
void selinux_xfrm_state_free(struct xfrm_state *x);
int selinux_xfrm_state_delete(struct xfrm_state *x);
-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
+int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl);
* LSM hook implementation that authorizes that a flow can use
* a xfrm policy rule.
*/
-int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
+int selinux_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
int rc;
u32 sel_sid;
- struct xfrm_sec_ctx *ctx;
/* Context sid is either set to label or ANY_ASSOC */
- if ((ctx = xp->security)) {
+ if (ctx) {
if (!selinux_authorizable_ctx(ctx))
return -EINVAL;
sel_sid = ctx->ctx_sid;
- }
- else
+ } else
/*
* All flows should be treated as polmatch'ing an
* otherwise applicable "non-labeled" policy. This
NULL);
if (rc == -EACCES)
- rc = -ESRCH;
+ return -ESRCH;
return rc;
}
* LSM hook implementation that allocs and transfers uctx spec to
* xfrm_policy.
*/
-int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
- struct xfrm_user_sec_ctx *uctx)
+int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
+ struct xfrm_user_sec_ctx *uctx)
{
int err;
- BUG_ON(!xp);
BUG_ON(!uctx);
- err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
+ err = selinux_xfrm_sec_ctx_alloc(ctxp, uctx, 0);
if (err == 0)
atomic_inc(&selinux_xfrm_refcount);
* LSM hook implementation that copies security data structure from old to
* new for policy cloning.
*/
-int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new)
+int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
+ struct xfrm_sec_ctx **new_ctxp)
{
- struct xfrm_sec_ctx *old_ctx, *new_ctx;
-
- old_ctx = old->security;
+ struct xfrm_sec_ctx *new_ctx;
if (old_ctx) {
- new_ctx = new->security = kmalloc(sizeof(*new_ctx) +
- old_ctx->ctx_len,
- GFP_KERNEL);
-
+ new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
+ GFP_KERNEL);
if (!new_ctx)
return -ENOMEM;
memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
+ *new_ctxp = new_ctx;
}
return 0;
}
/*
- * LSM hook implementation that frees xfrm_policy security information.
+ * LSM hook implementation that frees xfrm_sec_ctx security information.
*/
-void selinux_xfrm_policy_free(struct xfrm_policy *xp)
+void selinux_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
{
- struct xfrm_sec_ctx *ctx = xp->security;
if (ctx)
kfree(ctx);
}
/*
* LSM hook implementation that authorizes deletion of labeled policies.
*/
-int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
+int selinux_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
struct task_security_struct *tsec = current->security;
- struct xfrm_sec_ctx *ctx = xp->security;
int rc = 0;
if (ctx) {