Commit 03e1ad7b authored by Paul Moore's avatar Paul Moore Committed by David S. Miller

LSM: Make the Labeled IPsec hooks more stack friendly

The xfrm_get_policy() and xfrm_add_pol_expire() put some rather large structs
on the stack to work around the LSM API.  This patch attempts to fix that
problem by changing the LSM API to require only the relevant "security"
pointers instead of the entire SPD entry; we do this for all of the
security_xfrm_policy*() functions to keep things consistent.
Signed-off-by: default avatarPaul Moore <paul.moore@hp.com>
Acked-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 00447872
...@@ -910,24 +910,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) ...@@ -910,24 +910,24 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* Security hooks for XFRM operations. * Security hooks for XFRM operations.
* *
* @xfrm_policy_alloc_security: * @xfrm_policy_alloc_security:
* @xp contains the xfrm_policy being added to Security Policy Database * @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy
* used by the XFRM system. * Database used by the XFRM system.
* @sec_ctx contains the security context information being provided by * @sec_ctx contains the security context information being provided by
* the user-level policy update program (e.g., setkey). * the user-level policy update program (e.g., setkey).
* Allocate a security structure to the xp->security field; the security * Allocate a security structure to the xp->security field; the security
* field is initialized to NULL when the xfrm_policy is allocated. * field is initialized to NULL when the xfrm_policy is allocated.
* Return 0 if operation was successful (memory to allocate, legal context) * Return 0 if operation was successful (memory to allocate, legal context)
* @xfrm_policy_clone_security: * @xfrm_policy_clone_security:
* @old contains an existing xfrm_policy in the SPD. * @old_ctx contains an existing xfrm_sec_ctx.
* @new contains a new xfrm_policy being cloned from old. * @new_ctxp contains a new xfrm_sec_ctx being cloned from old.
* Allocate a security structure to the new->security field * Allocate a security structure in new_ctxp that contains the
* that contains the information from the old->security field. * information from the old_ctx structure.
* Return 0 if operation was successful (memory to allocate). * Return 0 if operation was successful (memory to allocate).
* @xfrm_policy_free_security: * @xfrm_policy_free_security:
* @xp contains the xfrm_policy * @ctx contains the xfrm_sec_ctx
* Deallocate xp->security. * Deallocate xp->security.
* @xfrm_policy_delete_security: * @xfrm_policy_delete_security:
* @xp contains the xfrm_policy. * @ctx contains the xfrm_sec_ctx.
* Authorize deletion of xp->security. * Authorize deletion of xp->security.
* @xfrm_state_alloc_security: * @xfrm_state_alloc_security:
* @x contains the xfrm_state being added to the Security Association * @x contains the xfrm_state being added to the Security Association
...@@ -947,7 +947,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) ...@@ -947,7 +947,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @x contains the xfrm_state. * @x contains the xfrm_state.
* Authorize deletion of x->security. * Authorize deletion of x->security.
* @xfrm_policy_lookup: * @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. * checked.
* @fl_secid contains the flow security label that is used to authorize * @fl_secid contains the flow security label that is used to authorize
* access to the policy xp. * access to the policy xp.
...@@ -1454,17 +1454,17 @@ struct security_operations { ...@@ -1454,17 +1454,17 @@ struct security_operations {
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM #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); struct xfrm_user_sec_ctx *sec_ctx);
int (*xfrm_policy_clone_security) (struct xfrm_policy *old, struct xfrm_policy *new); int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
void (*xfrm_policy_free_security) (struct xfrm_policy *xp); void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
int (*xfrm_policy_delete_security) (struct xfrm_policy *xp); int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
int (*xfrm_state_alloc_security) (struct xfrm_state *x, int (*xfrm_state_alloc_security) (struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx, struct xfrm_user_sec_ctx *sec_ctx,
u32 secid); u32 secid);
void (*xfrm_state_free_security) (struct xfrm_state *x); void (*xfrm_state_free_security) (struct xfrm_state *x);
int (*xfrm_state_delete_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, int (*xfrm_state_pol_flow_match)(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl); struct xfrm_policy *xp, struct flowi *fl);
int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall); int (*xfrm_decode_session)(struct sk_buff *skb, u32 *secid, int ckall);
...@@ -2562,16 +2562,16 @@ static inline void security_inet_conn_established(struct sock *sk, ...@@ -2562,16 +2562,16 @@ static inline void security_inet_conn_established(struct sock *sk,
#ifdef CONFIG_SECURITY_NETWORK_XFRM #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);
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);
void security_xfrm_policy_free(struct xfrm_policy *xp); void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx);
int security_xfrm_policy_delete(struct xfrm_policy *xp); 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(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
int security_xfrm_state_alloc_acquire(struct xfrm_state *x, int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid); struct xfrm_sec_ctx *polsec, u32 secid);
int security_xfrm_state_delete(struct xfrm_state *x); int security_xfrm_state_delete(struct xfrm_state *x);
void security_xfrm_state_free(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, int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl); struct xfrm_policy *xp, struct flowi *fl);
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid); int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid);
...@@ -2579,21 +2579,21 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl); ...@@ -2579,21 +2579,21 @@ void security_skb_classify_flow(struct sk_buff *skb, struct flowi *fl);
#else /* CONFIG_SECURITY_NETWORK_XFRM */ #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; 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; 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;
} }
...@@ -2619,7 +2619,7 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x) ...@@ -2619,7 +2619,7 @@ static inline int security_xfrm_state_delete(struct xfrm_state *x)
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; return 0;
} }
......
...@@ -2292,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h ...@@ -2292,7 +2292,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
goto out; goto out;
} }
err = security_xfrm_policy_alloc(xp, uctx); err = security_xfrm_policy_alloc(&xp->security, uctx);
kfree(uctx); kfree(uctx);
if (err) if (err)
...@@ -2352,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg ...@@ -2352,10 +2352,11 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
int err; int err;
struct sadb_address *sa; struct sadb_address *sa;
struct sadb_x_policy *pol; struct sadb_x_policy *pol;
struct xfrm_policy *xp, tmp; struct xfrm_policy *xp;
struct xfrm_selector sel; struct xfrm_selector sel;
struct km_event c; struct km_event c;
struct sadb_x_sec_ctx *sec_ctx; 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], if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
...@@ -2385,25 +2386,23 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg ...@@ -2385,25 +2386,23 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
sel.dport_mask = htons(0xffff); sel.dport_mask = htons(0xffff);
sec_ctx = (struct sadb_x_sec_ctx *) ext_hdrs[SADB_X_EXT_SEC_CTX-1]; 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) { if (sec_ctx != NULL) {
struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); struct xfrm_user_sec_ctx *uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx);
if (!uctx) if (!uctx)
return -ENOMEM; return -ENOMEM;
err = security_xfrm_policy_alloc(&tmp, uctx); err = security_xfrm_policy_alloc(&pol_ctx, uctx);
kfree(uctx); kfree(uctx);
if (err) if (err)
return err; return err;
} } else
pol_ctx = NULL;
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);
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) if (xp == NULL)
return -ENOENT; return -ENOENT;
...@@ -3298,7 +3297,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, ...@@ -3298,7 +3297,7 @@ static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
if ((*dir = verify_sec_ctx_len(p))) if ((*dir = verify_sec_ctx_len(p)))
goto out; goto out;
uctx = pfkey_sadb2xfrm_user_sec_ctx(sec_ctx); 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); kfree(uctx);
if (*dir) if (*dir)
......
...@@ -263,7 +263,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy) ...@@ -263,7 +263,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
list_del(&policy->bytype); list_del(&policy->bytype);
write_unlock_bh(&xfrm_policy_lock); write_unlock_bh(&xfrm_policy_lock);
security_xfrm_policy_free(policy); security_xfrm_policy_free(policy->security);
kfree(policy); kfree(policy);
} }
EXPORT_SYMBOL(xfrm_policy_destroy); EXPORT_SYMBOL(xfrm_policy_destroy);
...@@ -676,7 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir, ...@@ -676,7 +676,8 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
xfrm_sec_ctx_match(ctx, pol->security)) { xfrm_sec_ctx_match(ctx, pol->security)) {
xfrm_pol_hold(pol); xfrm_pol_hold(pol);
if (delete) { if (delete) {
*err = security_xfrm_policy_delete(pol); *err = security_xfrm_policy_delete(
pol->security);
if (*err) { if (*err) {
write_unlock_bh(&xfrm_policy_lock); write_unlock_bh(&xfrm_policy_lock);
return pol; return pol;
...@@ -718,7 +719,8 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete, ...@@ -718,7 +719,8 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete,
if (pol->type == type && pol->index == id) { if (pol->type == type && pol->index == id) {
xfrm_pol_hold(pol); xfrm_pol_hold(pol);
if (delete) { if (delete) {
*err = security_xfrm_policy_delete(pol); *err = security_xfrm_policy_delete(
pol->security);
if (*err) { if (*err) {
write_unlock_bh(&xfrm_policy_lock); write_unlock_bh(&xfrm_policy_lock);
return pol; return pol;
...@@ -756,7 +758,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) ...@@ -756,7 +758,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
&xfrm_policy_inexact[dir], bydst) { &xfrm_policy_inexact[dir], bydst) {
if (pol->type != type) if (pol->type != type)
continue; continue;
err = security_xfrm_policy_delete(pol); err = security_xfrm_policy_delete(pol->security);
if (err) { if (err) {
xfrm_audit_policy_delete(pol, 0, xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid, audit_info->loginuid,
...@@ -770,7 +772,8 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info) ...@@ -770,7 +772,8 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
bydst) { bydst) {
if (pol->type != type) if (pol->type != type)
continue; continue;
err = security_xfrm_policy_delete(pol); err = security_xfrm_policy_delete(
pol->security);
if (err) { if (err) {
xfrm_audit_policy_delete(pol, 0, xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid, audit_info->loginuid,
...@@ -931,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl, ...@@ -931,7 +934,8 @@ static int xfrm_policy_match(struct xfrm_policy *pol, struct flowi *fl,
match = xfrm_selector_match(sel, fl, family); match = xfrm_selector_match(sel, fl, family);
if (match) if (match)
ret = security_xfrm_policy_lookup(pol, fl->secid, dir); ret = security_xfrm_policy_lookup(pol->security, fl->secid,
dir);
return ret; return ret;
} }
...@@ -1048,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc ...@@ -1048,8 +1052,9 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(struct sock *sk, int dir, struc
int err = 0; int err = 0;
if (match) { if (match) {
err = security_xfrm_policy_lookup(pol, fl->secid, err = security_xfrm_policy_lookup(pol->security,
policy_to_flow_dir(dir)); fl->secid,
policy_to_flow_dir(dir));
if (!err) if (!err)
xfrm_pol_hold(pol); xfrm_pol_hold(pol);
else if (err == -ESRCH) else if (err == -ESRCH)
...@@ -1138,7 +1143,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir) ...@@ -1138,7 +1143,8 @@ static struct xfrm_policy *clone_policy(struct xfrm_policy *old, int dir)
if (newp) { if (newp) {
newp->selector = old->selector; newp->selector = old->selector;
if (security_xfrm_policy_clone(old, newp)) { if (security_xfrm_policy_clone(old->security,
&newp->security)) {
kfree(newp); kfree(newp);
return NULL; /* ENOMEM */ return NULL; /* ENOMEM */
} }
......
...@@ -959,7 +959,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs ...@@ -959,7 +959,7 @@ static int copy_from_user_sec_ctx(struct xfrm_policy *pol, struct nlattr **attrs
return 0; return 0;
uctx = nla_data(rt); 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, static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
...@@ -1143,7 +1143,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1143,7 +1143,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
NETLINK_CB(skb).sid); NETLINK_CB(skb).sid);
if (err) { if (err) {
security_xfrm_policy_free(xp); security_xfrm_policy_free(xp->security);
kfree(xp); kfree(xp);
return err; return err;
} }
...@@ -1337,22 +1337,23 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1337,22 +1337,23 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err); xp = xfrm_policy_byid(type, p->dir, p->index, delete, &err);
else { else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_policy tmp; struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs); err = verify_sec_ctx_len(attrs);
if (err) if (err)
return err; return err;
memset(&tmp, 0, sizeof(struct xfrm_policy));
if (rt) { if (rt) {
struct xfrm_user_sec_ctx *uctx = nla_data(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; return err;
} } else
xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, ctx = NULL;
xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx,
delete, &err); delete, &err);
security_xfrm_policy_free(&tmp); security_xfrm_policy_free(ctx);
} }
if (xp == NULL) if (xp == NULL)
return -ENOENT; return -ENOENT;
...@@ -1572,26 +1573,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -1572,26 +1573,26 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err); xp = xfrm_policy_byid(type, p->dir, p->index, 0, &err);
else { else {
struct nlattr *rt = attrs[XFRMA_SEC_CTX]; struct nlattr *rt = attrs[XFRMA_SEC_CTX];
struct xfrm_policy tmp; struct xfrm_sec_ctx *ctx;
err = verify_sec_ctx_len(attrs); err = verify_sec_ctx_len(attrs);
if (err) if (err)
return err; return err;
memset(&tmp, 0, sizeof(struct xfrm_policy));
if (rt) { if (rt) {
struct xfrm_user_sec_ctx *uctx = nla_data(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; return err;
} } else
xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, ctx = NULL;
0, &err); xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, ctx, 0, &err);
security_xfrm_policy_free(&tmp); security_xfrm_policy_free(ctx);
} }
if (xp == NULL) if (xp == NULL)
return -ENOENT; return -ENOENT;
read_lock(&xp->lock); read_lock(&xp->lock);
if (xp->dead) { if (xp->dead) {
read_unlock(&xp->lock); read_unlock(&xp->lock);
......
...@@ -876,22 +876,23 @@ static inline void dummy_req_classify_flow(const struct request_sock *req, ...@@ -876,22 +876,23 @@ static inline void dummy_req_classify_flow(const struct request_sock *req,
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
#ifdef CONFIG_SECURITY_NETWORK_XFRM #ifdef CONFIG_SECURITY_NETWORK_XFRM
static int dummy_xfrm_policy_alloc_security(struct xfrm_policy *xp, static int dummy_xfrm_policy_alloc_security(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx) struct xfrm_user_sec_ctx *sec_ctx)
{ {
return 0; 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; 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;
} }
...@@ -911,7 +912,8 @@ static int dummy_xfrm_state_delete_security(struct xfrm_state *x) ...@@ -911,7 +912,8 @@ static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
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; return 0;
} }
......
...@@ -1014,26 +1014,27 @@ void security_inet_conn_established(struct sock *sk, ...@@ -1014,26 +1014,27 @@ void security_inet_conn_established(struct sock *sk,
#ifdef CONFIG_SECURITY_NETWORK_XFRM #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); 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); 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) int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
...@@ -1065,9 +1066,9 @@ void security_xfrm_state_free(struct xfrm_state *x) ...@@ -1065,9 +1066,9 @@ void security_xfrm_state_free(struct xfrm_state *x)
security_ops->xfrm_state_free_security(x); 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, int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
......
...@@ -7,16 +7,17 @@ ...@@ -7,16 +7,17 @@
#ifndef _SELINUX_XFRM_H_ #ifndef _SELINUX_XFRM_H_
#define _SELINUX_XFRM_H_ #define _SELINUX_XFRM_H_
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *sec_ctx); struct xfrm_user_sec_ctx *sec_ctx);
int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new); int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
void selinux_xfrm_policy_free(struct xfrm_policy *xp); struct xfrm_sec_ctx **new_ctxp);
int selinux_xfrm_policy_delete(struct xfrm_policy *xp); 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, int selinux_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx, u32 secid); struct xfrm_user_sec_ctx *sec_ctx, u32 secid);
void selinux_xfrm_state_free(struct xfrm_state *x); void selinux_xfrm_state_free(struct xfrm_state *x);
int selinux_xfrm_state_delete(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, int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl); struct xfrm_policy *xp, struct flowi *fl);
......
...@@ -77,20 +77,18 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x) ...@@ -77,20 +77,18 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
* LSM hook implementation that authorizes that a flow can use * LSM hook implementation that authorizes that a flow can use
* a xfrm policy rule. * 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; int rc;
u32 sel_sid; u32 sel_sid;
struct xfrm_sec_ctx *ctx;
/* Context sid is either set to label or ANY_ASSOC */ /* Context sid is either set to label or ANY_ASSOC */
if ((ctx = xp->security)) { if (ctx) {
if (!selinux_authorizable_ctx(ctx)) if (!selinux_authorizable_ctx(ctx))
return -EINVAL; return -EINVAL;
sel_sid = ctx->ctx_sid; sel_sid = ctx->ctx_sid;
} } else
else
/* /*
* All flows should be treated as polmatch'ing an * All flows should be treated as polmatch'ing an
* otherwise applicable "non-labeled" policy. This * otherwise applicable "non-labeled" policy. This
...@@ -103,7 +101,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir) ...@@ -103,7 +101,7 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
NULL); NULL);
if (rc == -EACCES) if (rc == -EACCES)
rc = -ESRCH; return -ESRCH;
return rc; return rc;
} }
...@@ -287,15 +285,14 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, ...@@ -287,15 +285,14 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
* LSM hook implementation that allocs and transfers uctx spec to * LSM hook implementation that allocs and transfers uctx spec to
* xfrm_policy. * xfrm_policy.
*/ */
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp,
struct xfrm_user_sec_ctx *uctx) struct xfrm_user_sec_ctx *uctx)
{ {
int err; int err;
BUG_ON(!xp);
BUG_ON(!uctx); 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) if (err == 0)
atomic_inc(&selinux_xfrm_refcount); atomic_inc(&selinux_xfrm_refcount);
...@@ -307,32 +304,29 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, ...@@ -307,32 +304,29 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
* LSM hook implementation that copies security data structure from old to * LSM hook implementation that copies security data structure from old to
* new for policy cloning. * 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; struct xfrm_sec_ctx *new_ctx;
old_ctx = old->security;
if (old_ctx) { if (old_ctx) {
new_ctx = new->security = kmalloc(sizeof(*new_ctx) + new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
old_ctx->ctx_len, GFP_KERNEL);
GFP_KERNEL);
if (!new_ctx) if (!new_ctx)
return -ENOMEM; return -ENOMEM;
memcpy(new_ctx, old_ctx, sizeof(*new_ctx)); memcpy(new_ctx, old_ctx, sizeof(*new_ctx));
memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len); memcpy(new_ctx->ctx_str, old_ctx->ctx_str, new_ctx->ctx_len);
*new_ctxp = new_ctx;
} }
return 0; 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) if (ctx)
kfree(ctx); kfree(ctx);
} }
...@@ -340,10 +334,9 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp) ...@@ -340,10 +334,9 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp)
/* /*
* LSM hook implementation that authorizes deletion of labeled policies. * 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 task_security_struct *tsec = current->security;
struct xfrm_sec_ctx *ctx = xp->security;
int rc = 0; int rc = 0;
if (ctx) { if (ctx) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment