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