// SPDX-License-Identifier: GPL-2.0-or-later /* * cn_proc.c - process events connector * * Copyright (C) Matt Helsley, IBM Corp. 2005 * Based on cn_fork.c by Guillaume Thouvenin <guillaume.thouvenin@bull.net> * Original copyright notice follows: * Copyright (C) 2005 BULL SA.
*/
/* * Size of a cn_msg followed by a proc_event structure. Since the * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we * add one 4-byte word to the size here, and then start the actual * cn_msg structure 4 bytes into the stack buffer. The result is that * the immediately following proc_event structure is aligned to 8 bytes.
*/ #define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4)
/* See comment above; we test our assumption about sizeof struct cn_msg here. */ staticinlinestruct cn_msg *buffer_to_cn_msg(__u8 *buffer)
{
BUILD_BUG_ON(sizeof(struct cn_msg) != 20); return (struct cn_msg *)(buffer + 4);
}
/* local_event.count is used as the sequence number of the netlink message */ struct local_event {
local_lock_t lock;
__u32 count;
}; static DEFINE_PER_CPU(struct local_event, local_event) = {
.lock = INIT_LOCAL_LOCK(lock),
};
if (!dsk || !dsk->sk_user_data || !data) return 0;
ptr = (__u32 *)data;
what = *ptr++;
exit_code = *ptr;
val = ((struct proc_input *)(dsk->sk_user_data))->event_type;
mc_op = ((struct proc_input *)(dsk->sk_user_data))->mcast_op;
if (mc_op == PROC_CN_MCAST_IGNORE) return 1;
if ((__u32)val == PROC_EVENT_ALL) return 0;
/* * Drop packet if we have to report only non-zero exit status * (PROC_EVENT_NONZERO_EXIT) and exit status is 0
*/ if (((__u32)val & PROC_EVENT_NONZERO_EXIT) &&
(what == PROC_EVENT_EXIT)) { if (exit_code) return 0;
}
/* * local_lock() disables preemption during send to ensure the messages * are ordered according to their sequence numbers. * * If cn_netlink_send() fails, the data is not sent.
*/
filter_data[0] = ((struct proc_event *)msg->data)->what; if (filter_data[0] == PROC_EVENT_EXIT) {
filter_data[1] =
((struct proc_event *)msg->data)->event_data.exit.exit_code;
} else {
filter_data[1] = 0;
}
memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
msg->ack = 0; /* not used */
msg->len = sizeof(*ev);
msg->flags = 0; /* not used */
send_msg(msg);
}
/* * Send an acknowledgement message to userspace * * Use 0 for success, EFOO otherwise. * Note: this is the negative of conventional kernel error * values because it's not being returned via syscall return * mechanisms.
*/ staticvoid cn_proc_ack(int err, int rcvd_seq, int rcvd_ack)
{ struct cn_msg *msg; struct proc_event *ev;
__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
if (atomic_read(&proc_event_num_listeners) < 1) return;
/** * cn_proc_mcast_ctl * @msg: message sent from userspace via the connector * @nsp: NETLINK_CB of the client's socket buffer
*/ staticvoid cn_proc_mcast_ctl(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{ enum proc_cn_mcast_op mc_op = 0, prev_mc_op = 0; struct proc_input *pinput = NULL; enum proc_cn_event ev_type = 0; int err = 0, initial = 0; struct sock *sk = NULL;
/* * Events are reported with respect to the initial pid * and user namespaces so ignore requestors from * other namespaces.
*/ if ((current_user_ns() != &init_user_ns) ||
!task_is_in_init_pid_ns(current)) return;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.