xref: /aosp_15_r20/system/logging/logd/libaudit/libaudit.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker  * Copyright 2012, Samsung Telecommunications of America
3*598139dcSAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
4*598139dcSAndroid Build Coastguard Worker  *
5*598139dcSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*598139dcSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*598139dcSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*598139dcSAndroid Build Coastguard Worker  *
9*598139dcSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*598139dcSAndroid Build Coastguard Worker  *
11*598139dcSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*598139dcSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*598139dcSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*598139dcSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*598139dcSAndroid Build Coastguard Worker  * limitations under the License.
16*598139dcSAndroid Build Coastguard Worker  *
17*598139dcSAndroid Build Coastguard Worker  * Written by William Roberts <[email protected]>
18*598139dcSAndroid Build Coastguard Worker  *
19*598139dcSAndroid Build Coastguard Worker  */
20*598139dcSAndroid Build Coastguard Worker 
21*598139dcSAndroid Build Coastguard Worker #include "libaudit.h"
22*598139dcSAndroid Build Coastguard Worker 
23*598139dcSAndroid Build Coastguard Worker #include <errno.h>
24*598139dcSAndroid Build Coastguard Worker #include <string.h>
25*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
26*598139dcSAndroid Build Coastguard Worker 
27*598139dcSAndroid Build Coastguard Worker #include <limits>
28*598139dcSAndroid Build Coastguard Worker 
29*598139dcSAndroid Build Coastguard Worker /**
30*598139dcSAndroid Build Coastguard Worker  * Waits for an ack from the kernel
31*598139dcSAndroid Build Coastguard Worker  * @param fd
32*598139dcSAndroid Build Coastguard Worker  *  The netlink socket fd
33*598139dcSAndroid Build Coastguard Worker  * @return
34*598139dcSAndroid Build Coastguard Worker  *  This function returns 0 on success, else -errno.
35*598139dcSAndroid Build Coastguard Worker  */
get_ack(int fd)36*598139dcSAndroid Build Coastguard Worker static int get_ack(int fd) {
37*598139dcSAndroid Build Coastguard Worker     struct audit_message rep = {};
38*598139dcSAndroid Build Coastguard Worker     int rc = audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, MSG_PEEK);
39*598139dcSAndroid Build Coastguard Worker     if (rc < 0) {
40*598139dcSAndroid Build Coastguard Worker         return rc;
41*598139dcSAndroid Build Coastguard Worker     }
42*598139dcSAndroid Build Coastguard Worker 
43*598139dcSAndroid Build Coastguard Worker     if (rep.nlh.nlmsg_type == NLMSG_ERROR) {
44*598139dcSAndroid Build Coastguard Worker         audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, 0);
45*598139dcSAndroid Build Coastguard Worker         rc = reinterpret_cast<struct nlmsgerr*>(rep.data)->error;
46*598139dcSAndroid Build Coastguard Worker         return rc;
47*598139dcSAndroid Build Coastguard Worker     }
48*598139dcSAndroid Build Coastguard Worker 
49*598139dcSAndroid Build Coastguard Worker     return 0;
50*598139dcSAndroid Build Coastguard Worker }
51*598139dcSAndroid Build Coastguard Worker 
52*598139dcSAndroid Build Coastguard Worker /**
53*598139dcSAndroid Build Coastguard Worker  *
54*598139dcSAndroid Build Coastguard Worker  * @param fd
55*598139dcSAndroid Build Coastguard Worker  *  The netlink socket fd
56*598139dcSAndroid Build Coastguard Worker  * @param type
57*598139dcSAndroid Build Coastguard Worker  *  The type of netlink message
58*598139dcSAndroid Build Coastguard Worker  * @param data
59*598139dcSAndroid Build Coastguard Worker  *  The data to send
60*598139dcSAndroid Build Coastguard Worker  * @param size
61*598139dcSAndroid Build Coastguard Worker  *  The length of the data in bytes
62*598139dcSAndroid Build Coastguard Worker  * @return
63*598139dcSAndroid Build Coastguard Worker  *  This function returns a positive sequence number on success, else -errno.
64*598139dcSAndroid Build Coastguard Worker  */
audit_send(int fd,int type,const void * data,size_t size)65*598139dcSAndroid Build Coastguard Worker static int audit_send(int fd, int type, const void* data, size_t size) {
66*598139dcSAndroid Build Coastguard Worker     struct sockaddr_nl addr = {.nl_family = AF_NETLINK};
67*598139dcSAndroid Build Coastguard Worker 
68*598139dcSAndroid Build Coastguard Worker     /* Set up the netlink headers */
69*598139dcSAndroid Build Coastguard Worker     struct audit_message req = {};
70*598139dcSAndroid Build Coastguard Worker     req.nlh.nlmsg_type = static_cast<uint16_t>(type);
71*598139dcSAndroid Build Coastguard Worker     req.nlh.nlmsg_len = NLMSG_SPACE(size);
72*598139dcSAndroid Build Coastguard Worker     req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
73*598139dcSAndroid Build Coastguard Worker 
74*598139dcSAndroid Build Coastguard Worker     /*
75*598139dcSAndroid Build Coastguard Worker      * Check for a valid fd, even though sendto would catch this, its easier
76*598139dcSAndroid Build Coastguard Worker      * to always blindly increment the sequence number
77*598139dcSAndroid Build Coastguard Worker      */
78*598139dcSAndroid Build Coastguard Worker     if (fd < 0) {
79*598139dcSAndroid Build Coastguard Worker         return -EBADF;
80*598139dcSAndroid Build Coastguard Worker     }
81*598139dcSAndroid Build Coastguard Worker 
82*598139dcSAndroid Build Coastguard Worker     /* Ensure the message is not too big */
83*598139dcSAndroid Build Coastguard Worker     if (NLMSG_SPACE(size) > MAX_AUDIT_MESSAGE_LENGTH) {
84*598139dcSAndroid Build Coastguard Worker         return -EINVAL;
85*598139dcSAndroid Build Coastguard Worker     }
86*598139dcSAndroid Build Coastguard Worker 
87*598139dcSAndroid Build Coastguard Worker     /* Only memcpy in the data if it was specified */
88*598139dcSAndroid Build Coastguard Worker     if (size && data) {
89*598139dcSAndroid Build Coastguard Worker         memcpy(NLMSG_DATA(&req.nlh), data, size);
90*598139dcSAndroid Build Coastguard Worker     }
91*598139dcSAndroid Build Coastguard Worker 
92*598139dcSAndroid Build Coastguard Worker     /*
93*598139dcSAndroid Build Coastguard Worker      * Only increment the sequence number on a guarantee
94*598139dcSAndroid Build Coastguard Worker      * you will send it to the kernel.
95*598139dcSAndroid Build Coastguard Worker      */
96*598139dcSAndroid Build Coastguard Worker     static uint32_t sequence = 0;
97*598139dcSAndroid Build Coastguard Worker     if (sequence == std::numeric_limits<uint32_t>::max()) {
98*598139dcSAndroid Build Coastguard Worker         sequence = 1;
99*598139dcSAndroid Build Coastguard Worker     } else {
100*598139dcSAndroid Build Coastguard Worker         sequence++;
101*598139dcSAndroid Build Coastguard Worker     }
102*598139dcSAndroid Build Coastguard Worker     req.nlh.nlmsg_seq = sequence;
103*598139dcSAndroid Build Coastguard Worker 
104*598139dcSAndroid Build Coastguard Worker     ssize_t rc = TEMP_FAILURE_RETRY(
105*598139dcSAndroid Build Coastguard Worker             sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr)));
106*598139dcSAndroid Build Coastguard Worker 
107*598139dcSAndroid Build Coastguard Worker     /* Not all the bytes were sent */
108*598139dcSAndroid Build Coastguard Worker     if (rc < 0) {
109*598139dcSAndroid Build Coastguard Worker         return -errno;
110*598139dcSAndroid Build Coastguard Worker     } else if ((uint32_t)rc != req.nlh.nlmsg_len) {
111*598139dcSAndroid Build Coastguard Worker         return -EPROTO;
112*598139dcSAndroid Build Coastguard Worker     }
113*598139dcSAndroid Build Coastguard Worker 
114*598139dcSAndroid Build Coastguard Worker     /* We sent all the bytes, get the ack */
115*598139dcSAndroid Build Coastguard Worker     rc = get_ack(fd);
116*598139dcSAndroid Build Coastguard Worker 
117*598139dcSAndroid Build Coastguard Worker     /* If the ack failed, return the error, else return the sequence number */
118*598139dcSAndroid Build Coastguard Worker     rc = (rc == 0) ? (int)sequence : rc;
119*598139dcSAndroid Build Coastguard Worker 
120*598139dcSAndroid Build Coastguard Worker     return rc;
121*598139dcSAndroid Build Coastguard Worker }
122*598139dcSAndroid Build Coastguard Worker 
audit_setup(int fd,pid_t pid)123*598139dcSAndroid Build Coastguard Worker int audit_setup(int fd, pid_t pid) {
124*598139dcSAndroid Build Coastguard Worker     /*
125*598139dcSAndroid Build Coastguard Worker      * In order to set the auditd PID we send an audit message over the netlink
126*598139dcSAndroid Build Coastguard Worker      * socket with the pid field of the status struct set to our current pid,
127*598139dcSAndroid Build Coastguard Worker      * and the the mask set to AUDIT_STATUS_PID
128*598139dcSAndroid Build Coastguard Worker      */
129*598139dcSAndroid Build Coastguard Worker     struct audit_status status = {
130*598139dcSAndroid Build Coastguard Worker             .mask = AUDIT_STATUS_PID,
131*598139dcSAndroid Build Coastguard Worker             .pid = static_cast<uint32_t>(pid),
132*598139dcSAndroid Build Coastguard Worker     };
133*598139dcSAndroid Build Coastguard Worker 
134*598139dcSAndroid Build Coastguard Worker     /* Let the kernel know this pid will be registering for audit events */
135*598139dcSAndroid Build Coastguard Worker     int rc = audit_send(fd, AUDIT_SET, &status, sizeof(status));
136*598139dcSAndroid Build Coastguard Worker     if (rc < 0) {
137*598139dcSAndroid Build Coastguard Worker         return rc;
138*598139dcSAndroid Build Coastguard Worker     }
139*598139dcSAndroid Build Coastguard Worker 
140*598139dcSAndroid Build Coastguard Worker     /*
141*598139dcSAndroid Build Coastguard Worker      * In a request where we need to wait for a response, wait for the message
142*598139dcSAndroid Build Coastguard Worker      * and discard it. This message confirms and sync's us with the kernel.
143*598139dcSAndroid Build Coastguard Worker      * This daemon is now registered as the audit logger.
144*598139dcSAndroid Build Coastguard Worker      *
145*598139dcSAndroid Build Coastguard Worker      * TODO
146*598139dcSAndroid Build Coastguard Worker      * If the daemon dies and restarts the message didn't come back,
147*598139dcSAndroid Build Coastguard Worker      * so I went to non-blocking and it seemed to fix the bug.
148*598139dcSAndroid Build Coastguard Worker      * Need to investigate further.
149*598139dcSAndroid Build Coastguard Worker      */
150*598139dcSAndroid Build Coastguard Worker     struct audit_message rep = {};
151*598139dcSAndroid Build Coastguard Worker     audit_get_reply(fd, &rep, GET_REPLY_NONBLOCKING, 0);
152*598139dcSAndroid Build Coastguard Worker 
153*598139dcSAndroid Build Coastguard Worker     return 0;
154*598139dcSAndroid Build Coastguard Worker }
155*598139dcSAndroid Build Coastguard Worker 
audit_open()156*598139dcSAndroid Build Coastguard Worker int audit_open() {
157*598139dcSAndroid Build Coastguard Worker     return socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT);
158*598139dcSAndroid Build Coastguard Worker }
159*598139dcSAndroid Build Coastguard Worker 
audit_rate_limit(int fd,uint32_t limit)160*598139dcSAndroid Build Coastguard Worker int audit_rate_limit(int fd, uint32_t limit) {
161*598139dcSAndroid Build Coastguard Worker     struct audit_status status = {
162*598139dcSAndroid Build Coastguard Worker             .mask = AUDIT_STATUS_RATE_LIMIT, .rate_limit = limit, /* audit entries per second */
163*598139dcSAndroid Build Coastguard Worker     };
164*598139dcSAndroid Build Coastguard Worker     return audit_send(fd, AUDIT_SET, &status, sizeof(status));
165*598139dcSAndroid Build Coastguard Worker }
166*598139dcSAndroid Build Coastguard Worker 
audit_get_reply(int fd,struct audit_message * rep,reply_t block,int peek)167*598139dcSAndroid Build Coastguard Worker int audit_get_reply(int fd, struct audit_message* rep, reply_t block, int peek) {
168*598139dcSAndroid Build Coastguard Worker     if (fd < 0) {
169*598139dcSAndroid Build Coastguard Worker         return -EBADF;
170*598139dcSAndroid Build Coastguard Worker     }
171*598139dcSAndroid Build Coastguard Worker 
172*598139dcSAndroid Build Coastguard Worker     int flags = (block == GET_REPLY_NONBLOCKING) ? MSG_DONTWAIT : 0;
173*598139dcSAndroid Build Coastguard Worker     flags |= peek;
174*598139dcSAndroid Build Coastguard Worker 
175*598139dcSAndroid Build Coastguard Worker     /*
176*598139dcSAndroid Build Coastguard Worker      * Get the data from the netlink socket but on error we need to be carefull,
177*598139dcSAndroid Build Coastguard Worker      * the interface shows that EINTR can never be returned, other errors,
178*598139dcSAndroid Build Coastguard Worker      * however, can be returned.
179*598139dcSAndroid Build Coastguard Worker      */
180*598139dcSAndroid Build Coastguard Worker     struct sockaddr_nl nladdr;
181*598139dcSAndroid Build Coastguard Worker     socklen_t nladdrlen = sizeof(nladdr);
182*598139dcSAndroid Build Coastguard Worker     ssize_t len = TEMP_FAILURE_RETRY(
183*598139dcSAndroid Build Coastguard Worker             recvfrom(fd, rep, sizeof(*rep), flags, (struct sockaddr*)&nladdr, &nladdrlen));
184*598139dcSAndroid Build Coastguard Worker 
185*598139dcSAndroid Build Coastguard Worker     /*
186*598139dcSAndroid Build Coastguard Worker      * EAGAIN should be re-tried until success or another error manifests.
187*598139dcSAndroid Build Coastguard Worker      */
188*598139dcSAndroid Build Coastguard Worker     if (len < 0) {
189*598139dcSAndroid Build Coastguard Worker         if (block == GET_REPLY_NONBLOCKING && errno == EAGAIN) {
190*598139dcSAndroid Build Coastguard Worker             /* If request is non blocking and errno is EAGAIN, just return 0 */
191*598139dcSAndroid Build Coastguard Worker             return 0;
192*598139dcSAndroid Build Coastguard Worker         }
193*598139dcSAndroid Build Coastguard Worker         return -errno;
194*598139dcSAndroid Build Coastguard Worker     }
195*598139dcSAndroid Build Coastguard Worker 
196*598139dcSAndroid Build Coastguard Worker     if (nladdrlen != sizeof(nladdr)) {
197*598139dcSAndroid Build Coastguard Worker         return -EPROTO;
198*598139dcSAndroid Build Coastguard Worker     }
199*598139dcSAndroid Build Coastguard Worker 
200*598139dcSAndroid Build Coastguard Worker     /* Make sure the netlink message was not spoof'd */
201*598139dcSAndroid Build Coastguard Worker     if (nladdr.nl_pid) {
202*598139dcSAndroid Build Coastguard Worker         return -EINVAL;
203*598139dcSAndroid Build Coastguard Worker     }
204*598139dcSAndroid Build Coastguard Worker 
205*598139dcSAndroid Build Coastguard Worker     /* Check if the reply from the kernel was ok */
206*598139dcSAndroid Build Coastguard Worker     if (!NLMSG_OK(&rep->nlh, (size_t)len)) {
207*598139dcSAndroid Build Coastguard Worker         return len == sizeof(*rep) ? -EFBIG : -EBADE;
208*598139dcSAndroid Build Coastguard Worker     }
209*598139dcSAndroid Build Coastguard Worker 
210*598139dcSAndroid Build Coastguard Worker     return 0;
211*598139dcSAndroid Build Coastguard Worker }
212*598139dcSAndroid Build Coastguard Worker 
audit_close(int fd)213*598139dcSAndroid Build Coastguard Worker void audit_close(int fd) {
214*598139dcSAndroid Build Coastguard Worker     close(fd);
215*598139dcSAndroid Build Coastguard Worker }
216*598139dcSAndroid Build Coastguard Worker 
audit_log_android_avc_message(int fd,const char * msg)217*598139dcSAndroid Build Coastguard Worker int audit_log_android_avc_message(int fd, const char* msg) {
218*598139dcSAndroid Build Coastguard Worker     size_t len;
219*598139dcSAndroid Build Coastguard Worker 
220*598139dcSAndroid Build Coastguard Worker     if (__builtin_add_overflow(strlen(msg), 1, &len)) {
221*598139dcSAndroid Build Coastguard Worker         return -EINVAL;
222*598139dcSAndroid Build Coastguard Worker     }
223*598139dcSAndroid Build Coastguard Worker 
224*598139dcSAndroid Build Coastguard Worker     return audit_send(fd, AUDIT_USER_AVC, msg, len);
225*598139dcSAndroid Build Coastguard Worker }
226