forked from Minki/linux
audit/stable-5.14 PR 20210629
-----BEGIN PGP SIGNATURE----- iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAmDbjZ4UHHBhdWxAcGF1 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXMMMRAAgwwYgJ8pqac21co0rLCEMLdnSKvu ueaqCa0F/c+UJ9VmHZ0eDr4FHFgCxKamUP1+/Zn4U53tc483mX/Kz6blGd91hz1K YnYJGK/tlOmhOJtaZOsp0saRrYn/62kO5tyzp+mhNKje5ON4ICA5jR3Wz+B+RDSM GXH8EDuxKVkAuqpTZHm79a8LL2G9uDre2uWWHehDxLNAOuLxK/3DnObHRdEi4ZcV 9MSFljLnSocFdLOPRL2R05LQ2ce18NHkTW+FMzPbTezLP4lm62lEsAYOQ1vvUm0A MoncR4bFGMPYbM5WQmwiDDBBVoo6+HB5Q0AK6fbZwaIJYNFCCc0ytKKyfSyyIaRK 8qSaGeXpUU4nHeygeHvhz7uOVFJfG+WXWRM2WIOwUWU0KKbvCSJ3UDM3cuJHIQol jv2yuYIZQcz/tXTsOn59ivjsxXclsb3d1Z6FmligaoAoASCerCgeGkhDC4CwHYg5 qZHxE/rtiZxzgZ15cghxITOcGzOVEeYqbo9FzD5aXh66MGzOkrtYwJ+CCVTSx27O uco6PKelVI2EJ9v4KeQtIMOFDU/ZyJrde/q2otfqQoSaR12Jarpi0qL/5ossuR2B bEqNN6sX22++QfvLZOAJ8EmYjzkmDfs4q4LYQxMpQfw27OTcK17rXcnI//mmRbUr SrCuVW3mF8FzxJc= =1bAZ -----END PGP SIGNATURE----- Merge tag 'audit-pr-20210629' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit Pull audit updates from Paul Moore: "Another merge window, another small audit pull request. Four patches in total: one is cosmetic, one removes an unnecessary initialization, one renames some enum values to prevent name collisions, and one converts list_del()/list_add() to list_move(). None of these are earth shattering and all pass the audit-testsuite tests while merging cleanly on top of your tree from earlier today" * tag 'audit-pr-20210629' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit: audit: remove unnecessary 'ret' initialization audit: remove trailing spaces and tabs audit: Use list_move instead of list_del/list_add audit: Rename enum audit_state constants to avoid AUDIT_DISABLED redefinition audit: add blank line after variable declarations
This commit is contained in:
commit
290fe0fa6f
@ -48,7 +48,7 @@
|
||||
* 2500 - 2999 future user space (maybe integrity labels and related events)
|
||||
*
|
||||
* Messages from 1000-1199 are bi-directional. 1200-1299 & 2100 - 2999 are
|
||||
* exclusively user space. 1300-2099 is kernel --> user space
|
||||
* exclusively user space. 1300-2099 is kernel --> user space
|
||||
* communication.
|
||||
*/
|
||||
#define AUDIT_GET 1000 /* Get status */
|
||||
@ -78,7 +78,7 @@
|
||||
#define AUDIT_LAST_USER_MSG 1199
|
||||
#define AUDIT_FIRST_USER_MSG2 2100 /* More user space messages */
|
||||
#define AUDIT_LAST_USER_MSG2 2999
|
||||
|
||||
|
||||
#define AUDIT_DAEMON_START 1200 /* Daemon startup record */
|
||||
#define AUDIT_DAEMON_END 1201 /* Daemon normal stop record */
|
||||
#define AUDIT_DAEMON_ABORT 1202 /* Daemon error stop record */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/* audit -- definition of audit_context structure and supporting types
|
||||
/* audit -- definition of audit_context structure and supporting types
|
||||
*
|
||||
* Copyright 2003-2004 Red Hat, Inc.
|
||||
* Copyright 2005 Hewlett-Packard Development Company, L.P.
|
||||
@ -21,16 +21,16 @@
|
||||
a per-task filter. At syscall entry, the audit_state is augmented by
|
||||
the syscall filter. */
|
||||
enum audit_state {
|
||||
AUDIT_DISABLED, /* Do not create per-task audit_context.
|
||||
AUDIT_STATE_DISABLED, /* Do not create per-task audit_context.
|
||||
* No syscall-specific audit records can
|
||||
* be generated. */
|
||||
AUDIT_BUILD_CONTEXT, /* Create the per-task audit_context,
|
||||
AUDIT_STATE_BUILD, /* Create the per-task audit_context,
|
||||
* and fill it in at syscall
|
||||
* entry time. This makes a full
|
||||
* syscall record available if some
|
||||
* other part of the kernel decides it
|
||||
* should be recorded. */
|
||||
AUDIT_RECORD_CONTEXT /* Create the per-task audit_context,
|
||||
AUDIT_STATE_RECORD /* Create the per-task audit_context,
|
||||
* always fill it in at syscall entry
|
||||
* time, and always write out the audit
|
||||
* record at syscall exit time. */
|
||||
@ -322,7 +322,7 @@ static inline int audit_signal_info_syscall(struct task_struct *t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define audit_filter_inodes(t, c) AUDIT_DISABLED
|
||||
#define audit_filter_inodes(t, c) AUDIT_STATE_DISABLED
|
||||
#endif /* CONFIG_AUDITSYSCALL */
|
||||
|
||||
extern char *audit_unpack_string(void **bufp, size_t *remain, size_t len);
|
||||
|
@ -689,8 +689,7 @@ void audit_trim_trees(void)
|
||||
|
||||
tree = container_of(cursor.next, struct audit_tree, list);
|
||||
get_tree(tree);
|
||||
list_del(&cursor);
|
||||
list_add(&cursor, &tree->list);
|
||||
list_move(&cursor, &tree->list);
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
|
||||
err = kern_path(tree->pathname, 0, &path);
|
||||
@ -899,8 +898,7 @@ int audit_tag_tree(char *old, char *new)
|
||||
|
||||
tree = container_of(cursor.next, struct audit_tree, list);
|
||||
get_tree(tree);
|
||||
list_del(&cursor);
|
||||
list_add(&cursor, &tree->list);
|
||||
list_move(&cursor, &tree->list);
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
|
||||
err = kern_path(tree->pathname, 0, &path2);
|
||||
@ -925,8 +923,7 @@ int audit_tag_tree(char *old, char *new)
|
||||
mutex_lock(&audit_filter_mutex);
|
||||
spin_lock(&hash_lock);
|
||||
if (!tree->goner) {
|
||||
list_del(&tree->list);
|
||||
list_add(&tree->list, &tree_list);
|
||||
list_move(&tree->list, &tree_list);
|
||||
}
|
||||
spin_unlock(&hash_lock);
|
||||
put_tree(tree);
|
||||
@ -937,8 +934,7 @@ int audit_tag_tree(char *old, char *new)
|
||||
|
||||
tree = container_of(barrier.prev, struct audit_tree, list);
|
||||
get_tree(tree);
|
||||
list_del(&tree->list);
|
||||
list_add(&tree->list, &barrier);
|
||||
list_move(&tree->list, &barrier);
|
||||
mutex_unlock(&audit_filter_mutex);
|
||||
|
||||
if (!failed) {
|
||||
|
@ -160,6 +160,7 @@ static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
|
||||
static int audit_match_perm(struct audit_context *ctx, int mask)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
if (unlikely(!ctx))
|
||||
return 0;
|
||||
n = ctx->major;
|
||||
@ -231,7 +232,7 @@ static void audit_set_auditable(struct audit_context *ctx)
|
||||
{
|
||||
if (!ctx->prio) {
|
||||
ctx->prio = 1;
|
||||
ctx->current_state = AUDIT_RECORD_CONTEXT;
|
||||
ctx->current_state = AUDIT_STATE_RECORD;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +240,7 @@ static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
|
||||
{
|
||||
struct audit_tree_refs *p = ctx->trees;
|
||||
int left = ctx->tree_count;
|
||||
|
||||
if (likely(left)) {
|
||||
p->c[--left] = chunk;
|
||||
ctx->tree_count = left;
|
||||
@ -259,6 +261,7 @@ static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
|
||||
static int grow_tree_refs(struct audit_context *ctx)
|
||||
{
|
||||
struct audit_tree_refs *p = ctx->trees;
|
||||
|
||||
ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
|
||||
if (!ctx->trees) {
|
||||
ctx->trees = p;
|
||||
@ -277,6 +280,7 @@ static void unroll_tree_refs(struct audit_context *ctx,
|
||||
{
|
||||
struct audit_tree_refs *q;
|
||||
int n;
|
||||
|
||||
if (!p) {
|
||||
/* we started with empty chain */
|
||||
p = ctx->first_trees;
|
||||
@ -303,6 +307,7 @@ static void unroll_tree_refs(struct audit_context *ctx,
|
||||
static void free_tree_refs(struct audit_context *ctx)
|
||||
{
|
||||
struct audit_tree_refs *p, *q;
|
||||
|
||||
for (p = ctx->first_trees; p; p = q) {
|
||||
q = p->next;
|
||||
kfree(p);
|
||||
@ -313,6 +318,7 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
|
||||
{
|
||||
struct audit_tree_refs *p;
|
||||
int n;
|
||||
|
||||
if (!tree)
|
||||
return 0;
|
||||
/* full ones */
|
||||
@ -337,13 +343,13 @@ static int audit_compare_uid(kuid_t uid,
|
||||
{
|
||||
struct audit_names *n;
|
||||
int rc;
|
||||
|
||||
|
||||
if (name) {
|
||||
rc = audit_uid_comparator(uid, f->op, name->uid);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
if (ctx) {
|
||||
list_for_each_entry(n, &ctx->names_list, list) {
|
||||
rc = audit_uid_comparator(uid, f->op, n->uid);
|
||||
@ -361,13 +367,13 @@ static int audit_compare_gid(kgid_t gid,
|
||||
{
|
||||
struct audit_names *n;
|
||||
int rc;
|
||||
|
||||
|
||||
if (name) {
|
||||
rc = audit_gid_comparator(gid, f->op, name->gid);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
if (ctx) {
|
||||
list_for_each_entry(n, &ctx->names_list, list) {
|
||||
rc = audit_gid_comparator(gid, f->op, n->gid);
|
||||
@ -751,10 +757,10 @@ static int audit_filter_rules(struct task_struct *tsk,
|
||||
}
|
||||
switch (rule->action) {
|
||||
case AUDIT_NEVER:
|
||||
*state = AUDIT_DISABLED;
|
||||
*state = AUDIT_STATE_DISABLED;
|
||||
break;
|
||||
case AUDIT_ALWAYS:
|
||||
*state = AUDIT_RECORD_CONTEXT;
|
||||
*state = AUDIT_STATE_RECORD;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
@ -773,14 +779,14 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
|
||||
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) {
|
||||
if (audit_filter_rules(tsk, &e->rule, NULL, NULL,
|
||||
&state, true)) {
|
||||
if (state == AUDIT_RECORD_CONTEXT)
|
||||
if (state == AUDIT_STATE_RECORD)
|
||||
*key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
|
||||
rcu_read_unlock();
|
||||
return state;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return AUDIT_BUILD_CONTEXT;
|
||||
return AUDIT_STATE_BUILD;
|
||||
}
|
||||
|
||||
static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
|
||||
@ -802,7 +808,7 @@ static int audit_in_mask(const struct audit_krule *rule, unsigned long val)
|
||||
/* At syscall exit time, this filter is called if the audit_state is
|
||||
* not low enough that auditing cannot take place, but is also not
|
||||
* high enough that we already know we have to write an audit record
|
||||
* (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
|
||||
* (i.e., the state is AUDIT_STATE_BUILD).
|
||||
*/
|
||||
static void audit_filter_syscall(struct task_struct *tsk,
|
||||
struct audit_context *ctx)
|
||||
@ -923,7 +929,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
|
||||
if (!context)
|
||||
return NULL;
|
||||
context->state = state;
|
||||
context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
|
||||
context->prio = state == AUDIT_STATE_RECORD ? ~0ULL : 0;
|
||||
INIT_LIST_HEAD(&context->killed_trees);
|
||||
INIT_LIST_HEAD(&context->names_list);
|
||||
context->fds[0] = -1;
|
||||
@ -950,7 +956,7 @@ int audit_alloc(struct task_struct *tsk)
|
||||
return 0; /* Return if not auditing. */
|
||||
|
||||
state = audit_filter_task(tsk, &key);
|
||||
if (state == AUDIT_DISABLED) {
|
||||
if (state == AUDIT_STATE_DISABLED) {
|
||||
clear_task_syscall_work(tsk, SYSCALL_AUDIT);
|
||||
return 0;
|
||||
}
|
||||
@ -1225,6 +1231,7 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||
switch (context->type) {
|
||||
case AUDIT_SOCKETCALL: {
|
||||
int nargs = context->socketcall.nargs;
|
||||
|
||||
audit_log_format(ab, "nargs=%d", nargs);
|
||||
for (i = 0; i < nargs; i++)
|
||||
audit_log_format(ab, " a%d=%lx", i,
|
||||
@ -1240,6 +1247,7 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||
if (osid) {
|
||||
char *ctx = NULL;
|
||||
u32 len;
|
||||
|
||||
if (security_secid_to_secctx(osid, &ctx, &len)) {
|
||||
audit_log_format(ab, " osid=%u", osid);
|
||||
*call_panic = 1;
|
||||
@ -1289,6 +1297,7 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||
break;
|
||||
case AUDIT_MQ_GETSETATTR: {
|
||||
struct mq_attr *attr = &context->mq_getsetattr.mqstat;
|
||||
|
||||
audit_log_format(ab,
|
||||
"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
|
||||
"mq_curmsgs=%ld ",
|
||||
@ -1325,6 +1334,7 @@ static void show_special(struct audit_context *context, int *call_panic)
|
||||
static inline int audit_proctitle_rtrim(char *proctitle, int len)
|
||||
{
|
||||
char *end = proctitle + len - 1;
|
||||
|
||||
while (end > proctitle && !isprint(*end))
|
||||
end--;
|
||||
|
||||
@ -1513,6 +1523,7 @@ static void audit_log_exit(void)
|
||||
|
||||
case AUDIT_BPRM_FCAPS: {
|
||||
struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
|
||||
|
||||
audit_log_format(ab, "fver=%x", axs->fcap_ver);
|
||||
audit_log_cap(ab, "fp", &axs->fcap.permitted);
|
||||
audit_log_cap(ab, "fi", &axs->fcap.inheritable);
|
||||
@ -1628,7 +1639,7 @@ void __audit_free(struct task_struct *tsk)
|
||||
|
||||
audit_filter_syscall(tsk, context);
|
||||
audit_filter_inodes(tsk, context);
|
||||
if (context->current_state == AUDIT_RECORD_CONTEXT)
|
||||
if (context->current_state == AUDIT_STATE_RECORD)
|
||||
audit_log_exit();
|
||||
}
|
||||
|
||||
@ -1647,7 +1658,7 @@ void __audit_free(struct task_struct *tsk)
|
||||
* Fill in audit context at syscall entry. This only happens if the
|
||||
* audit context was created when the task was created and the state or
|
||||
* filters demand the audit context be built. If the state from the
|
||||
* per-task filter or from the per-syscall filter is AUDIT_RECORD_CONTEXT,
|
||||
* per-task filter or from the per-syscall filter is AUDIT_STATE_RECORD,
|
||||
* then the record will be written at syscall exit time (otherwise, it
|
||||
* will only be written if another part of the kernel requests that it
|
||||
* be written).
|
||||
@ -1664,11 +1675,11 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
|
||||
BUG_ON(context->in_syscall || context->name_count);
|
||||
|
||||
state = context->state;
|
||||
if (state == AUDIT_DISABLED)
|
||||
if (state == AUDIT_STATE_DISABLED)
|
||||
return;
|
||||
|
||||
context->dummy = !audit_n_rules;
|
||||
if (!context->dummy && state == AUDIT_BUILD_CONTEXT) {
|
||||
if (!context->dummy && state == AUDIT_STATE_BUILD) {
|
||||
context->prio = 0;
|
||||
if (auditd_test_task(current))
|
||||
return;
|
||||
@ -1693,7 +1704,7 @@ void __audit_syscall_entry(int major, unsigned long a1, unsigned long a2,
|
||||
* @return_code: return value of the syscall
|
||||
*
|
||||
* Tear down after system call. If the audit context has been marked as
|
||||
* auditable (either because of the AUDIT_RECORD_CONTEXT state from
|
||||
* auditable (either because of the AUDIT_STATE_RECORD state from
|
||||
* filtering, or because some other part of the kernel wrote an audit
|
||||
* message), then write out the syscall information. In call cases,
|
||||
* free the names stored from getname().
|
||||
@ -1735,12 +1746,12 @@ void __audit_syscall_exit(int success, long return_code)
|
||||
|
||||
audit_filter_syscall(current, context);
|
||||
audit_filter_inodes(current, context);
|
||||
if (context->current_state == AUDIT_RECORD_CONTEXT)
|
||||
if (context->current_state == AUDIT_STATE_RECORD)
|
||||
audit_log_exit();
|
||||
}
|
||||
|
||||
context->in_syscall = 0;
|
||||
context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
|
||||
context->prio = context->state == AUDIT_STATE_RECORD ? ~0ULL : 0;
|
||||
|
||||
audit_free_module(context);
|
||||
audit_free_names(context);
|
||||
@ -1753,7 +1764,7 @@ void __audit_syscall_exit(int success, long return_code)
|
||||
context->sockaddr_len = 0;
|
||||
context->type = 0;
|
||||
context->fds[0] = -1;
|
||||
if (context->state != AUDIT_RECORD_CONTEXT) {
|
||||
if (context->state != AUDIT_STATE_RECORD) {
|
||||
kfree(context->filterkey);
|
||||
context->filterkey = NULL;
|
||||
}
|
||||
@ -1765,6 +1776,7 @@ static inline void handle_one(const struct inode *inode)
|
||||
struct audit_tree_refs *p;
|
||||
struct audit_chunk *chunk;
|
||||
int count;
|
||||
|
||||
if (likely(!inode->i_fsnotify_marks))
|
||||
return;
|
||||
context = audit_context();
|
||||
@ -1806,8 +1818,10 @@ retry:
|
||||
seq = read_seqbegin(&rename_lock);
|
||||
for(;;) {
|
||||
struct inode *inode = d_backing_inode(d);
|
||||
|
||||
if (inode && unlikely(inode->i_fsnotify_marks)) {
|
||||
struct audit_chunk *chunk;
|
||||
|
||||
chunk = audit_tree_lookup(inode);
|
||||
if (chunk) {
|
||||
if (unlikely(!put_tree_ref(context, chunk))) {
|
||||
@ -2203,7 +2217,7 @@ int auditsc_get_stamp(struct audit_context *ctx,
|
||||
*serial = ctx->serial;
|
||||
if (!ctx->prio) {
|
||||
ctx->prio = 1;
|
||||
ctx->current_state = AUDIT_RECORD_CONTEXT;
|
||||
ctx->current_state = AUDIT_STATE_RECORD;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -2285,6 +2299,7 @@ void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
|
||||
void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
|
||||
{
|
||||
struct audit_context *context = audit_context();
|
||||
|
||||
context->mq_getsetattr.mqdes = mqdes;
|
||||
context->mq_getsetattr.mqstat = *mqstat;
|
||||
context->type = AUDIT_MQ_GETSETATTR;
|
||||
@ -2298,6 +2313,7 @@ void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
|
||||
void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
|
||||
{
|
||||
struct audit_context *context = audit_context();
|
||||
|
||||
context->ipc.uid = ipcp->uid;
|
||||
context->ipc.gid = ipcp->gid;
|
||||
context->ipc.mode = ipcp->mode;
|
||||
@ -2362,6 +2378,7 @@ int __audit_socketcall(int nargs, unsigned long *args)
|
||||
void __audit_fd_pair(int fd1, int fd2)
|
||||
{
|
||||
struct audit_context *context = audit_context();
|
||||
|
||||
context->fds[0] = fd1;
|
||||
context->fds[1] = fd2;
|
||||
}
|
||||
@ -2379,6 +2396,7 @@ int __audit_sockaddr(int len, void *a)
|
||||
|
||||
if (!context->sockaddr) {
|
||||
void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
|
||||
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
context->sockaddr = p;
|
||||
@ -2510,6 +2528,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
|
||||
void __audit_log_capset(const struct cred *new, const struct cred *old)
|
||||
{
|
||||
struct audit_context *context = audit_context();
|
||||
|
||||
context->capset.pid = task_tgid_nr(current);
|
||||
context->capset.cap.effective = new->cap_effective;
|
||||
context->capset.cap.inheritable = new->cap_effective;
|
||||
@ -2521,6 +2540,7 @@ void __audit_log_capset(const struct cred *new, const struct cred *old)
|
||||
void __audit_mmap_fd(int fd, int flags)
|
||||
{
|
||||
struct audit_context *context = audit_context();
|
||||
|
||||
context->mmap.fd = fd;
|
||||
context->mmap.flags = flags;
|
||||
context->type = AUDIT_MMAP;
|
||||
@ -2686,6 +2706,7 @@ void audit_seccomp_actions_logged(const char *names, const char *old_names,
|
||||
struct list_head *audit_killed_trees(void)
|
||||
{
|
||||
struct audit_context *ctx = audit_context();
|
||||
|
||||
if (likely(!ctx || !ctx->in_syscall))
|
||||
return NULL;
|
||||
return &ctx->killed_trees;
|
||||
|
@ -119,7 +119,6 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
|
||||
return -EINVAL;
|
||||
ad->u.net->v6info.saddr = ip6->saddr;
|
||||
ad->u.net->v6info.daddr = ip6->daddr;
|
||||
ret = 0;
|
||||
/* IPv6 can have several extension header before the Transport header
|
||||
* skip them */
|
||||
offset = skb_network_offset(skb);
|
||||
|
Loading…
Reference in New Issue
Block a user