/* No auditing will take place until audit_initialized == AUDIT_INITIALIZED.
* (Initialization happens after skb_init is called.) */ #define AUDIT_DISABLED -1 #define AUDIT_UNINITIALIZED 0 #define AUDIT_INITIALIZED 1 staticint audit_initialized = AUDIT_UNINITIALIZED;
/* If audit_rate_limit is non-zero, limit the rate of sending audit records *tothatnumberpersecond.ThispreventsDoSattacks,butresultsin
* audit records being dropped. */ static u32 audit_rate_limit;
/* Number of outstanding audit_buffers allowed.
* When set to zero, this means unlimited. */ static u32 audit_backlog_limit = 64; #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ) static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
/* The identity of the user shutting down the audit system. */ static kuid_t audit_sig_uid = INVALID_UID; static pid_t audit_sig_pid = -1; staticstruct lsm_prop audit_sig_lsm;
/* Records can be lost in several ways: 0)[suppressedinaudit_alloc] 1)outofmemoryinaudit_log_start[kmallocofstructaudit_buffer] 2)outofmemoryinaudit_log_move[alloc_skb] 3)suppressedduetoaudit_rate_limit 4)suppressedduetoaudit_backlog_limit
*/ static atomic_t audit_lost = ATOMIC_INIT(0);
/* Monotonically increasing sum of time the kernel has spent *waitingwhilethebackloglimitisexceeded.
*/ static atomic_t audit_backlog_wait_time_actual = ATOMIC_INIT(0);
/* Hash for inode-based rules */ struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
staticstruct kmem_cache *audit_buffer_cache;
/* queue msgs to send via kauditd_task */ staticstruct sk_buff_head audit_queue; /* queue msgs due to temporary unicast send problems */ staticstruct sk_buff_head audit_retry_queue; /* queue msgs waiting for new auditd connection */ staticstruct sk_buff_head audit_hold_queue;
/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting *auditrecords.Sinceprintkusesa1024bytebuffer,thisbuffer
* should be at least that large. */ #define AUDIT_BUFSIZ 1024
/* The audit_buffer is used when formatting an audit record. The caller *locksbrieflytogettherecordoffthefreelistortoallocatethe *buffer,andlocksbrieflytosendthebuffertothenetlinklayeror *toplaceitonatransmitqueue.Multipleaudit_bufferscanbein
* use simultaneously. */ struct audit_buffer { struct sk_buff *skb; /* formatted skb ready to send */ struct audit_context *ctx; /* NULL or associated context */
gfp_t gfp_mask;
};
staticint audit_do_config_change(char *function_name, u32 *to_change, u32 new)
{ int allow_changes, rc = 0;
u32 old = *to_change;
/* check if we are locked */ if (audit_enabled == AUDIT_LOCKED)
allow_changes = 0; else
allow_changes = 1;
if (audit_enabled != AUDIT_OFF) {
rc = audit_log_config_change(function_name, new, old, allow_changes); if (rc)
allow_changes = 0;
}
/* If we are allowed, make the change */ if (allow_changes == 1)
*to_change = new; /* Not allowed, update reason */ elseif (rc == 0)
rc = -EPERM; return rc;
}
/** *kauditd_rehold_skb-Handleaauditrecordsendfailureintheholdqueue *@skb:auditrecord *@error:errorcode(unused) * *Description: *Thisshouldonlybeusedbythekauditd_threadwhenitfailstoflushthe *holdqueue.
*/ staticvoid kauditd_rehold_skb(struct sk_buff *skb, __always_unused int error)
{ /* put the record back in the queue */
skb_queue_tail(&audit_hold_queue, skb);
}
/** *kauditd_hold_skb-Queueanauditrecord,waitingforauditd *@skb:auditrecord *@error:errorcode * *Description: *Queuetheauditrecord,waitingforaninstanceofauditd.Whenthis *functioniscalledwehaven'tgivenupyetonsendingtherecord,butthings *arenotlookinggood.Thefirstthingwewanttodoistrytowritethe *recordviaprintkandthenseeifwewanttotryandholdontotherecord *andqueueit,ifwehaveroom.Ifwewanttoholdontotherecord,butwe *don'thaveroom,recordarecordlostmessage.
*/ staticvoid kauditd_hold_skb(struct sk_buff *skb, int error)
{ /* at this point it is uncertain if we will ever send this to auditd so
* try to send the message via printk before we go any further */
kauditd_printk_skb(skb);
/* can we just silently drop the message? */ if (!audit_default) goto drop;
/* the hold queue is only for when the daemon goes away completely, *not-EAGAINfailures;ifweareina-EAGAINstaterequeuethe *recordontheretryqueueunlessit'sfull,inwhichcasedropit
*/ if (error == -EAGAIN) { if (!audit_backlog_limit ||
skb_queue_len(&audit_retry_queue) < audit_backlog_limit) {
skb_queue_tail(&audit_retry_queue, skb); return;
}
audit_log_lost("kauditd retry queue overflow"); goto drop;
}
/* if we have room in the hold queue, queue the message */ if (!audit_backlog_limit ||
skb_queue_len(&audit_hold_queue) < audit_backlog_limit) {
skb_queue_tail(&audit_hold_queue, skb); return;
}
/* we have no other options - drop the message */
audit_log_lost("kauditd hold queue overflow");
drop:
kfree_skb(skb);
}
/* we have to drop the record, send it via printk as a last effort */
kauditd_printk_skb(skb);
audit_log_lost("kauditd retry queue overflow");
kfree_skb(skb);
}
/* if it isn't already broken, break the connection */
spin_lock_irqsave(&auditd_conn_lock, flags);
ac_old = rcu_dereference_protected(auditd_conn,
lockdep_is_held(&auditd_conn_lock)); if (ac && ac != ac_old) { /* someone already registered a new auditd connection */
spin_unlock_irqrestore(&auditd_conn_lock, flags); return;
}
rcu_assign_pointer(auditd_conn, NULL);
spin_unlock_irqrestore(&auditd_conn_lock, flags);
if (ac_old)
call_rcu(&ac_old->rcu, auditd_conn_free);
/* flush the retry queue to the hold queue, but don't touch the main
* queue since we need to process that normally for multicast */ while ((skb = skb_dequeue(&audit_retry_queue)))
kauditd_hold_skb(skb, -ECONNREFUSED);
}
/* NOTE: we can't call netlink_unicast while in the RCU section so *takeareferencetothenetworknamespaceandgrablocal *copiesofthenamespace,thesock,andtheportid;the *namespaceandsockaren'tgoingtogoawaywhileweholda *referenceandiftheportiddoesbecomeinvalidaftertheRCU
* section netlink_unicast() should safely return an error */
rcu_read_lock();
ac = rcu_dereference(auditd_conn); if (!ac) {
rcu_read_unlock();
kfree_skb(skb);
rc = -ECONNREFUSED; goto err;
}
net = get_net(ac->net);
sk = audit_get_sk(net);
portid = ac->portid;
rcu_read_unlock();
/* NOTE: kauditd_thread takes care of all our locking, we just use
* the netlink info passed to us (e.g. sk and portid) */
skb_tail = skb_peek_tail(queue); while ((skb != skb_tail) && (skb = skb_dequeue(queue))) { /* call the skb_hook for each skb we touch */ if (skb_hook)
(*skb_hook)(skb);
/* can we send to anyone via unicast? */ if (!sk) { if (err_hook)
(*err_hook)(skb, -ECONNREFUSED); continue;
}
retry: /* grab an extra skb reference in case of error */
skb_get(skb);
rc = netlink_unicast(sk, skb, portid, 0); if (rc < 0) { /* send failed - try a few times unless fatal error */ if (++failed >= retry_limit ||
rc == -ECONNREFUSED || rc == -EPERM) {
sk = NULL; if (err_hook)
(*err_hook)(skb, rc); if (rc == -EAGAIN)
rc = 0; /* continue to drain the queue */ continue;
} else goto retry;
} else { /* skb sent - drop the extra reference and continue */
consume_skb(skb);
failed = 0;
}
}
set_freezable(); while (!kthread_should_stop()) { /* NOTE: see the lock comments in auditd_send_unicast_skb() */
rcu_read_lock();
ac = rcu_dereference(auditd_conn); if (!ac) {
rcu_read_unlock(); goto main_queue;
}
net = get_net(ac->net);
sk = audit_get_sk(net);
portid = ac->portid;
rcu_read_unlock();
/* attempt to flush the hold queue */
rc = kauditd_send_queue(sk, portid,
&audit_hold_queue, UNICAST_RETRIES,
NULL, kauditd_rehold_skb); if (rc < 0) {
sk = NULL;
auditd_reset(ac); goto main_queue;
}
/* attempt to flush the retry queue */
rc = kauditd_send_queue(sk, portid,
&audit_retry_queue, UNICAST_RETRIES,
NULL, kauditd_hold_skb); if (rc < 0) {
sk = NULL;
auditd_reset(ac); goto main_queue;
}
main_queue: /* process the main queue - do the multicast send and attempt *unicast,dumpfailedrecordsendstotheretryqueue;if *sk==NULLduetopreviousfailureswewilljustdothe
* multicast send and move the record to the hold queue */
rc = kauditd_send_queue(sk, portid, &audit_queue, 1,
kauditd_send_multicast_skb,
(sk ?
kauditd_retry_skb : kauditd_hold_skb)); if (ac && rc < 0)
auditd_reset(ac);
sk = NULL;
/* drop our netns reference, no auditd sends past this line */ if (net) {
put_net(net);
net = NULL;
}
/* we have processed all the queues so wake everyone */
wake_up(&audit_backlog_wait);
/* NOTE: we want to wake up if there is anything on the queue, *regardlessofifanauditdisconnected,asweneedto *dothemulticastsendandrotaterecordsfromthe
* main queue to the retry/hold queues */
wait_event_freezable(kauditd_wait,
(skb_queue_len(&audit_queue) ? 1 : 0));
}
/* wait for parent to finish and send an ACK */
audit_ctl_lock();
audit_ctl_unlock();
while ((skb = __skb_dequeue(&dest->q)) != NULL)
netlink_unicast(sk, skb, dest->portid, 0);
put_net(dest->net);
kfree(dest);
return0;
}
struct sk_buff *audit_make_reply(int seq, int type, int done, int multi, constvoid *payload, int size)
{ struct sk_buff *skb; struct nlmsghdr *nlh; void *data; int flags = multi ? NLM_F_MULTI : 0; int t = done ? NLMSG_DONE : type;
skb = nlmsg_new(size, GFP_KERNEL); if (!skb) return NULL;
nlh = nlmsg_put(skb, 0, seq, t, size, flags); if (!nlh) goto out_kfree_skb;
data = nlmsg_data(nlh);
memcpy(data, payload, size); return skb;
out_kfree_skb:
kfree_skb(skb); return NULL;
}
staticvoid audit_free_reply(struct audit_reply *reply)
{ if (!reply) return;
kfree_skb(reply->skb); if (reply->net)
put_net(reply->net);
kfree(reply);
}
/* Ignore failure. It'll only happen if the sender goes away,
because our timeout is set to infinite. */
netlink_unicast(audit_get_sk(reply->net), reply->skb, reply->portid, 0);
reply->skb = NULL;
audit_free_reply(reply); return0;
}
/** *audit_send_reply-sendanauditreplymessagevianetlink *@request_skb:skbofrequestwearereplyingto(usedtotargetthereply) *@seq:sequencenumber *@type:auditmessagetype *@done:done(last)flag *@multi:multi-partmessageflag *@payload:payloaddata *@size:payloadsize * *Allocatesaskb,buildsthenetlinkmessage,andsendsittotheportid.
*/ staticvoid audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done, int multi, constvoid *payload, int size)
{ struct task_struct *tsk; struct audit_reply *reply;
reply = kzalloc(sizeof(*reply), GFP_KERNEL); if (!reply) return;
/* Only support initial user namespace for now. */ /* *WereturnECONNREFUSEDbecauseittricksuserspaceintothinking *thatauditwasnotconfiguredintothekernel.Lotsofusers *configuretheirPAMstack(becausethat'swhatthedistrodoes) *torejectloginifunabletosendmessagestoaudit.Ifwereturn *ECONNREFUSEDthePAMstackthinksthekerneldoesnothaveaudit *configuredinandwillletloginproceed.IfwereturnEPERM *userspacewillrejectalllogins.Thisshouldberemovedwhenwe *supportnoninitnamespaces!!
*/ if (current_user_ns() != &init_user_ns) return -ECONNREFUSED;
switch (msg_type) { case AUDIT_LIST: case AUDIT_ADD: case AUDIT_DEL: return -EOPNOTSUPP; case AUDIT_GET: case AUDIT_SET: case AUDIT_GET_FEATURE: case AUDIT_SET_FEATURE: case AUDIT_LIST_RULES: case AUDIT_ADD_RULE: case AUDIT_DEL_RULE: case AUDIT_SIGNAL_INFO: case AUDIT_TTY_GET: case AUDIT_TTY_SET: case AUDIT_TRIM: case AUDIT_MAKE_EQUIV: /* Only support auditd and auditctl in initial pid namespace
* for now. */ if (task_active_pid_ns(current) != &init_pid_ns) return -EPERM;
if (!netlink_capable(skb, CAP_AUDIT_CONTROL))
err = -EPERM; break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: if (!netlink_capable(skb, CAP_AUDIT_WRITE))
err = -EPERM; break; default: /* bad msg */
err = -EINVAL;
}
err = audit_netlink_ok(skb, msg_type); if (err) return err;
seq = nlh->nlmsg_seq;
data = nlmsg_data(nlh);
data_len = nlmsg_len(nlh);
switch (msg_type) { case AUDIT_GET: { struct audit_status s;
memset(&s, 0, sizeof(s));
s.enabled = audit_enabled;
s.failure = audit_failure; /* NOTE: use pid_vnr() so the PID is relative to the current
* namespace */
s.pid = auditd_pid_vnr();
s.rate_limit = audit_rate_limit;
s.backlog_limit = audit_backlog_limit;
s.lost = atomic_read(&audit_lost);
s.backlog = skb_queue_len(&audit_queue);
s.feature_bitmap = AUDIT_FEATURE_BITMAP_ALL;
s.backlog_wait_time = audit_backlog_wait_time;
s.backlog_wait_time_actual = atomic_read(&audit_backlog_wait_time_actual);
audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); break;
} case AUDIT_SET: { struct audit_status s;
memset(&s, 0, sizeof(s)); /* guard against past and future API changes */
memcpy(&s, data, min_t(size_t, sizeof(s), data_len)); if (s.mask & AUDIT_STATUS_ENABLED) {
err = audit_set_enabled(s.enabled); if (err < 0) return err;
} if (s.mask & AUDIT_STATUS_FAILURE) {
err = audit_set_failure(s.failure); if (err < 0) return err;
} if (s.mask & AUDIT_STATUS_PID) { /* NOTE: we are using the vnr PID functions below *becausethes.pidvalueisrelativetothe *namespaceofthecaller;atpresentthis *doesn'tmattermuchsinceyoucanreallyonly *runauditdfromtheinitialpidnamespace,but
* something to keep in mind if this changes */
pid_t new_pid = s.pid;
pid_t auditd_pid; struct pid *req_pid = task_tgid(current);
/* Sanity check - PID values must match. Setting
* pid to 0 is how auditd ends auditing. */ if (new_pid && (new_pid != pid_vnr(req_pid))) return -EINVAL;
/* test the auditd connection */
audit_replace(req_pid);
auditd_pid = auditd_pid_vnr(); if (auditd_pid) { /* replacing a healthy auditd is not allowed */ if (new_pid) {
audit_log_config_change("audit_pid",
new_pid, auditd_pid, 0); return -EEXIST;
} /* only current auditd can unregister itself */ if (pid_vnr(req_pid) != auditd_pid) {
audit_log_config_change("audit_pid",
new_pid, auditd_pid, 0); return -EACCES;
}
}
if (new_pid) { /* register a new auditd connection */
err = auditd_set(req_pid,
NETLINK_CB(skb).portid,
sock_net(NETLINK_CB(skb).sk),
skb, ack); if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid",
new_pid,
auditd_pid,
err ? 0 : 1); if (err) return err;
/* try to process any backlog */
wake_up_interruptible(&kauditd_wait);
} else { if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid",
new_pid,
auditd_pid, 1);
/* unregister the auditd connection */
auditd_reset(NULL);
}
} if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
err = audit_set_rate_limit(s.rate_limit); if (err < 0) return err;
} if (s.mask & AUDIT_STATUS_BACKLOG_LIMIT) {
err = audit_set_backlog_limit(s.backlog_limit); if (err < 0) return err;
} if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) { if (sizeof(s) > (size_t)nlh->nlmsg_len) return -EINVAL; if (s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME) return -EINVAL;
err = audit_set_backlog_wait_time(s.backlog_wait_time); if (err < 0) return err;
} if (s.mask == AUDIT_STATUS_LOST) {
u32 lost = atomic_xchg(&audit_lost, 0);
audit_log_config_change("lost", 0, lost, 1); return lost;
} if (s.mask == AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL) {
u32 actual = atomic_xchg(&audit_backlog_wait_time_actual, 0);
audit_log_config_change("backlog_wait_time_actual", 0, actual, 1); return actual;
} break;
} case AUDIT_GET_FEATURE:
err = audit_get_feature(skb); if (err) return err; break; case AUDIT_SET_FEATURE: if (data_len < sizeof(struct audit_features)) return -EINVAL;
err = audit_set_feature(data); if (err) return err; break; case AUDIT_USER: case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: if (!audit_enabled && msg_type != AUDIT_USER_AVC) return0; /* exit early if there isn't at least one character to print */ if (data_len < 2) return -EINVAL;
err = audit_filter(msg_type, AUDIT_FILTER_USER); if (err == 1) { /* match or error */ char *str = data;
memset(&s, 0, sizeof(s)); /* guard against past and future API changes */
memcpy(&s, data, min_t(size_t, sizeof(s), data_len)); /* check if new data is valid */ if ((s.enabled != 0 && s.enabled != 1) ||
(s.log_passwd != 0 && s.log_passwd != 1))
err = -EINVAL;
if (err)
t = READ_ONCE(current->signal->audit_tty); else {
t = s.enabled | (-s.log_passwd & AUDIT_TTY_LOG_PASSWD);
t = xchg(¤t->signal->audit_tty, t);
}
old.enabled = t & AUDIT_TTY_ENABLE;
old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD);
/* send an ack if the user asked for one and audit_receive_msg
* didn't already do it, or if there was an error. */ if (ack || err)
netlink_ack(skb, nlh, err, NULL);
/* can't block with the ctrl lock, so penalize the sender now */ if (audit_backlog_limit &&
(skb_queue_len(&audit_queue) > audit_backlog_limit)) {
DECLARE_WAITQUEUE(wait, current);
/* wake kauditd to try and flush the queue */
wake_up_interruptible(&kauditd_wait);
/* Log information about who is connecting to the audit multicast socket */ staticvoid audit_log_multicast(int group, constchar *op, int err)
{ conststruct cred *cred; struct tty_struct *tty; char comm[sizeof(current->comm)]; struct audit_buffer *ab;
if (!audit_enabled) return;
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_EVENT_LISTENER); if (!ab) return;
/* Run custom bind function on netlink socket group connect or bind requests. */ staticint audit_multicast_bind(struct net *net, int group)
{ int err = 0;
/* NOTE: you would think that we would want to check the auditd *connectionandpotentiallyresetithereifitlivesinthis *namespace,butsincetheauditdconnectiontrackingstructholdsa *referencetothisnamespace(seeauditd_set())weareonlyever
* going to get here after that connection has been released */
if (audit_initialized != AUDIT_INITIALIZED) return NULL;
if (unlikely(!audit_filter(type, AUDIT_FILTER_EXCLUDE))) return NULL;
/* NOTE: don't ever fail/sleep on these two conditions: *1.auditdgeneratedrecord-sinceweneedauditdtodrainthe *queue;also,whenwearecheckingforauditd,comparePIDsusing *task_tgid_vnr()sinceauditd_pidissetinaudit_receive_msg() *usingaPIDanchoredinthecaller'snamespace *2.generatorholdingtheaudit_cmd_mutex-wedon'twanttoblock *whileholdingthemutex,althoughwedopenalizethesender *laterinaudit_receive()whenitissafetoblock
*/ if (!(auditd_test_task(current) || audit_ctl_owner_current())) { long stime = audit_backlog_wait_time;
while (audit_backlog_limit &&
(skb_queue_len(&audit_queue) > audit_backlog_limit)) { /* wake kauditd to try and flush the queue */
wake_up_interruptible(&kauditd_wait);
/* sleep if we are allowed and we haven't exhausted our
* backlog wait limit */ if (gfpflags_allow_blocking(gfp_mask) && (stime > 0)) { long rtime = stime;
BUG_ON(!ab->skb);
skb = ab->skb;
avail = skb_tailroom(skb);
new_len = len<<1; if (new_len >= avail) { /* Round the buffer request up to the next multiple */
new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1);
avail = audit_expand(ab, new_len); if (!avail) return;
}
ptr = skb_tail_pointer(skb); for (i = 0; i < len; i++)
ptr = hex_byte_pack_upper(ptr, buf[i]);
*ptr = 0;
skb_put(skb, len << 1); /* new string is twice the old string */
}
/* This is a helper-function to print the escaped d_path */ void audit_log_d_path(struct audit_buffer *ab, constchar *prefix, conststruct path *path)
{ char *p, *pathname;
if (prefix)
audit_log_format(ab, "%s", prefix);
/* We will allow 11 spaces for ' (deleted)' to be appended */
pathname = kmalloc(PATH_MAX+11, ab->gfp_mask); if (!pathname) {
audit_log_format(ab, "\"<no_memory>\""); return;
}
p = d_path(path, pathname, PATH_MAX+11); if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */ /* FIXME: can we save some information here? */
audit_log_format(ab, "\"<too_long>\"");
} else
audit_log_untrustedstring(ab, p);
kfree(pathname);
}
/* Generate log with subject, operation, outcome. */
ab = audit_log_start(audit_context(), GFP_KERNEL, type); if (!ab) return;
audit_log_format(ab, "op=%s", operation);
audit_log_task_info(ab);
audit_log_format(ab, " res=0");
audit_log_end(ab);
}
/* global counter which is incremented every time something logs in */ static atomic_t session_id = ATOMIC_INIT(0);
staticint audit_set_loginuid_perm(kuid_t loginuid)
{ /* if we are unset, we don't need privs */ if (!audit_loginuid_set(current)) return0; /* if AUDIT_FEATURE_LOGINUID_IMMUTABLE means never ever allow a change*/ if (is_audit_feature_set(AUDIT_FEATURE_LOGINUID_IMMUTABLE)) return -EPERM; /* it is set, you need permission */ if (!capable(CAP_AUDIT_CONTROL)) return -EPERM; /* reject if this is not an unset and we don't allow that */ if (is_audit_feature_set(AUDIT_FEATURE_ONLY_UNSET_LOGINUID)
&& uid_valid(loginuid)) return -EPERM; return0;
}
rc = audit_set_loginuid_perm(loginuid); if (rc) goto out;
/* are we setting or clearing? */ if (uid_valid(loginuid)) {
sessionid = (unsignedint)atomic_inc_return(&session_id); if (unlikely(sessionid == AUDIT_SID_UNSET))
sessionid = (unsignedint)atomic_inc_return(&session_id);
}
if (audit_rate_check()) {
skb = ab->skb;
ab->skb = NULL;
/* setup the netlink header, see the comments in
* kauditd_send_multicast_skb() for length quirks */
nlh = nlmsg_hdr(skb);
nlh->nlmsg_len = skb->len - NLMSG_HDRLEN;
/* queue the netlink packet and poke the kauditd thread */
skb_queue_tail(&audit_queue, skb);
wake_up_interruptible(&kauditd_wait);
} else
audit_log_lost("rate limit exceeded");
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.110Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
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.