1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2019 Intel Corporation
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Worker #include "os_file.h"
7*61046927SAndroid Build Coastguard Worker #include "detect_os.h"
8*61046927SAndroid Build Coastguard Worker
9*61046927SAndroid Build Coastguard Worker #include <errno.h>
10*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
11*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
12*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
15*61046927SAndroid Build Coastguard Worker #include <io.h>
16*61046927SAndroid Build Coastguard Worker #define open _open
17*61046927SAndroid Build Coastguard Worker #define fdopen _fdopen
18*61046927SAndroid Build Coastguard Worker #define close _close
19*61046927SAndroid Build Coastguard Worker #define dup _dup
20*61046927SAndroid Build Coastguard Worker #define read _read
21*61046927SAndroid Build Coastguard Worker #define O_CREAT _O_CREAT
22*61046927SAndroid Build Coastguard Worker #define O_EXCL _O_EXCL
23*61046927SAndroid Build Coastguard Worker #define O_WRONLY _O_WRONLY
24*61046927SAndroid Build Coastguard Worker #else
25*61046927SAndroid Build Coastguard Worker #include <unistd.h>
26*61046927SAndroid Build Coastguard Worker #ifndef F_DUPFD_CLOEXEC
27*61046927SAndroid Build Coastguard Worker #define F_DUPFD_CLOEXEC 1030
28*61046927SAndroid Build Coastguard Worker #endif
29*61046927SAndroid Build Coastguard Worker #endif
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Worker
32*61046927SAndroid Build Coastguard Worker FILE *
os_file_create_unique(const char * filename,int filemode)33*61046927SAndroid Build Coastguard Worker os_file_create_unique(const char *filename, int filemode)
34*61046927SAndroid Build Coastguard Worker {
35*61046927SAndroid Build Coastguard Worker int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, filemode);
36*61046927SAndroid Build Coastguard Worker if (fd == -1)
37*61046927SAndroid Build Coastguard Worker return NULL;
38*61046927SAndroid Build Coastguard Worker return fdopen(fd, "w");
39*61046927SAndroid Build Coastguard Worker }
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
43*61046927SAndroid Build Coastguard Worker int
os_dupfd_cloexec(int fd)44*61046927SAndroid Build Coastguard Worker os_dupfd_cloexec(int fd)
45*61046927SAndroid Build Coastguard Worker {
46*61046927SAndroid Build Coastguard Worker /*
47*61046927SAndroid Build Coastguard Worker * On Windows child processes don't inherit handles by default:
48*61046927SAndroid Build Coastguard Worker * https://devblogs.microsoft.com/oldnewthing/20111216-00/?p=8873
49*61046927SAndroid Build Coastguard Worker */
50*61046927SAndroid Build Coastguard Worker return dup(fd);
51*61046927SAndroid Build Coastguard Worker }
52*61046927SAndroid Build Coastguard Worker #else
53*61046927SAndroid Build Coastguard Worker int
os_dupfd_cloexec(int fd)54*61046927SAndroid Build Coastguard Worker os_dupfd_cloexec(int fd)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker int minfd = 3;
57*61046927SAndroid Build Coastguard Worker int newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
58*61046927SAndroid Build Coastguard Worker
59*61046927SAndroid Build Coastguard Worker if (newfd >= 0)
60*61046927SAndroid Build Coastguard Worker return newfd;
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker if (errno != EINVAL)
63*61046927SAndroid Build Coastguard Worker return -1;
64*61046927SAndroid Build Coastguard Worker
65*61046927SAndroid Build Coastguard Worker newfd = fcntl(fd, F_DUPFD, minfd);
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker if (newfd < 0)
68*61046927SAndroid Build Coastguard Worker return -1;
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker long flags = fcntl(newfd, F_GETFD);
71*61046927SAndroid Build Coastguard Worker if (flags == -1) {
72*61046927SAndroid Build Coastguard Worker close(newfd);
73*61046927SAndroid Build Coastguard Worker return -1;
74*61046927SAndroid Build Coastguard Worker }
75*61046927SAndroid Build Coastguard Worker
76*61046927SAndroid Build Coastguard Worker if (fcntl(newfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
77*61046927SAndroid Build Coastguard Worker close(newfd);
78*61046927SAndroid Build Coastguard Worker return -1;
79*61046927SAndroid Build Coastguard Worker }
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker return newfd;
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker #endif
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker #include <fcntl.h>
86*61046927SAndroid Build Coastguard Worker #include <sys/stat.h>
87*61046927SAndroid Build Coastguard Worker
88*61046927SAndroid Build Coastguard Worker #if DETECT_OS_WINDOWS
89*61046927SAndroid Build Coastguard Worker typedef ptrdiff_t ssize_t;
90*61046927SAndroid Build Coastguard Worker #endif
91*61046927SAndroid Build Coastguard Worker
92*61046927SAndroid Build Coastguard Worker static ssize_t
readN(int fd,char * buf,size_t len)93*61046927SAndroid Build Coastguard Worker readN(int fd, char *buf, size_t len)
94*61046927SAndroid Build Coastguard Worker {
95*61046927SAndroid Build Coastguard Worker /* err was initially set to -ENODATA but in some BSD systems
96*61046927SAndroid Build Coastguard Worker * ENODATA is not defined and ENOATTR is used instead.
97*61046927SAndroid Build Coastguard Worker * As err is not returned by any function it can be initialized
98*61046927SAndroid Build Coastguard Worker * to -EFAULT that exists everywhere.
99*61046927SAndroid Build Coastguard Worker */
100*61046927SAndroid Build Coastguard Worker int err = -EFAULT;
101*61046927SAndroid Build Coastguard Worker size_t total = 0;
102*61046927SAndroid Build Coastguard Worker do {
103*61046927SAndroid Build Coastguard Worker ssize_t ret = read(fd, buf + total, len - total);
104*61046927SAndroid Build Coastguard Worker
105*61046927SAndroid Build Coastguard Worker if (ret < 0)
106*61046927SAndroid Build Coastguard Worker ret = -errno;
107*61046927SAndroid Build Coastguard Worker
108*61046927SAndroid Build Coastguard Worker if (ret == -EINTR || ret == -EAGAIN)
109*61046927SAndroid Build Coastguard Worker continue;
110*61046927SAndroid Build Coastguard Worker
111*61046927SAndroid Build Coastguard Worker if (ret <= 0) {
112*61046927SAndroid Build Coastguard Worker err = ret;
113*61046927SAndroid Build Coastguard Worker break;
114*61046927SAndroid Build Coastguard Worker }
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker total += ret;
117*61046927SAndroid Build Coastguard Worker } while (total != len);
118*61046927SAndroid Build Coastguard Worker
119*61046927SAndroid Build Coastguard Worker return total ? (ssize_t)total : err;
120*61046927SAndroid Build Coastguard Worker }
121*61046927SAndroid Build Coastguard Worker
122*61046927SAndroid Build Coastguard Worker #ifndef O_BINARY
123*61046927SAndroid Build Coastguard Worker /* Unix makes no distinction between text and binary files. */
124*61046927SAndroid Build Coastguard Worker #define O_BINARY 0
125*61046927SAndroid Build Coastguard Worker #endif
126*61046927SAndroid Build Coastguard Worker
127*61046927SAndroid Build Coastguard Worker char *
os_read_file(const char * filename,size_t * size)128*61046927SAndroid Build Coastguard Worker os_read_file(const char *filename, size_t *size)
129*61046927SAndroid Build Coastguard Worker {
130*61046927SAndroid Build Coastguard Worker /* Note that this also serves as a slight margin to avoid a 2x grow when
131*61046927SAndroid Build Coastguard Worker * the file is just a few bytes larger when we read it than when we
132*61046927SAndroid Build Coastguard Worker * fstat'ed it.
133*61046927SAndroid Build Coastguard Worker * The string's NULL terminator is also included in here.
134*61046927SAndroid Build Coastguard Worker */
135*61046927SAndroid Build Coastguard Worker size_t len = 64;
136*61046927SAndroid Build Coastguard Worker
137*61046927SAndroid Build Coastguard Worker int fd = open(filename, O_RDONLY | O_BINARY);
138*61046927SAndroid Build Coastguard Worker if (fd == -1) {
139*61046927SAndroid Build Coastguard Worker /* errno set by open() */
140*61046927SAndroid Build Coastguard Worker return NULL;
141*61046927SAndroid Build Coastguard Worker }
142*61046927SAndroid Build Coastguard Worker
143*61046927SAndroid Build Coastguard Worker /* Pre-allocate a buffer at least the size of the file if we can read
144*61046927SAndroid Build Coastguard Worker * that information.
145*61046927SAndroid Build Coastguard Worker */
146*61046927SAndroid Build Coastguard Worker struct stat stat;
147*61046927SAndroid Build Coastguard Worker if (fstat(fd, &stat) == 0)
148*61046927SAndroid Build Coastguard Worker len += stat.st_size;
149*61046927SAndroid Build Coastguard Worker
150*61046927SAndroid Build Coastguard Worker char *buf = malloc(len);
151*61046927SAndroid Build Coastguard Worker if (!buf) {
152*61046927SAndroid Build Coastguard Worker close(fd);
153*61046927SAndroid Build Coastguard Worker errno = -ENOMEM;
154*61046927SAndroid Build Coastguard Worker return NULL;
155*61046927SAndroid Build Coastguard Worker }
156*61046927SAndroid Build Coastguard Worker
157*61046927SAndroid Build Coastguard Worker ssize_t actually_read;
158*61046927SAndroid Build Coastguard Worker size_t offset = 0, remaining = len - 1;
159*61046927SAndroid Build Coastguard Worker while ((actually_read = readN(fd, buf + offset, remaining)) == (ssize_t)remaining) {
160*61046927SAndroid Build Coastguard Worker char *newbuf = realloc(buf, 2 * len);
161*61046927SAndroid Build Coastguard Worker if (!newbuf) {
162*61046927SAndroid Build Coastguard Worker free(buf);
163*61046927SAndroid Build Coastguard Worker close(fd);
164*61046927SAndroid Build Coastguard Worker errno = -ENOMEM;
165*61046927SAndroid Build Coastguard Worker return NULL;
166*61046927SAndroid Build Coastguard Worker }
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker buf = newbuf;
169*61046927SAndroid Build Coastguard Worker len *= 2;
170*61046927SAndroid Build Coastguard Worker offset += actually_read;
171*61046927SAndroid Build Coastguard Worker remaining = len - offset - 1;
172*61046927SAndroid Build Coastguard Worker }
173*61046927SAndroid Build Coastguard Worker
174*61046927SAndroid Build Coastguard Worker close(fd);
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker if (actually_read > 0)
177*61046927SAndroid Build Coastguard Worker offset += actually_read;
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker /* Final resize to actual size */
180*61046927SAndroid Build Coastguard Worker len = offset + 1;
181*61046927SAndroid Build Coastguard Worker char *newbuf = realloc(buf, len);
182*61046927SAndroid Build Coastguard Worker if (!newbuf) {
183*61046927SAndroid Build Coastguard Worker free(buf);
184*61046927SAndroid Build Coastguard Worker errno = -ENOMEM;
185*61046927SAndroid Build Coastguard Worker return NULL;
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker buf = newbuf;
188*61046927SAndroid Build Coastguard Worker
189*61046927SAndroid Build Coastguard Worker buf[offset] = '\0';
190*61046927SAndroid Build Coastguard Worker
191*61046927SAndroid Build Coastguard Worker if (size)
192*61046927SAndroid Build Coastguard Worker *size = offset;
193*61046927SAndroid Build Coastguard Worker
194*61046927SAndroid Build Coastguard Worker return buf;
195*61046927SAndroid Build Coastguard Worker }
196*61046927SAndroid Build Coastguard Worker
197*61046927SAndroid Build Coastguard Worker #if (DETECT_OS_LINUX || DETECT_OS_FREEBSD) && ALLOW_KCMP
198*61046927SAndroid Build Coastguard Worker
199*61046927SAndroid Build Coastguard Worker #include <sys/syscall.h>
200*61046927SAndroid Build Coastguard Worker #include <unistd.h>
201*61046927SAndroid Build Coastguard Worker
202*61046927SAndroid Build Coastguard Worker #if DETECT_OS_LINUX
203*61046927SAndroid Build Coastguard Worker /* copied from <linux/kcmp.h> */
204*61046927SAndroid Build Coastguard Worker #define KCMP_FILE 0
205*61046927SAndroid Build Coastguard Worker #endif
206*61046927SAndroid Build Coastguard Worker
207*61046927SAndroid Build Coastguard Worker #endif
208*61046927SAndroid Build Coastguard Worker
209*61046927SAndroid Build Coastguard Worker #if DETECT_OS_DRAGONFLY || DETECT_OS_FREEBSD
210*61046927SAndroid Build Coastguard Worker
211*61046927SAndroid Build Coastguard Worker #include "macros.h" /* ARRAY_SIZE */
212*61046927SAndroid Build Coastguard Worker
213*61046927SAndroid Build Coastguard Worker #include <sys/sysctl.h>
214*61046927SAndroid Build Coastguard Worker #if DETECT_OS_DRAGONFLY
215*61046927SAndroid Build Coastguard Worker #include <sys/kinfo.h>
216*61046927SAndroid Build Coastguard Worker typedef void *kvaddr_t;
217*61046927SAndroid Build Coastguard Worker #elif DETECT_OS_FREEBSD
218*61046927SAndroid Build Coastguard Worker #include <sys/file.h>
219*61046927SAndroid Build Coastguard Worker #define kinfo_file xfile
220*61046927SAndroid Build Coastguard Worker #define f_pid xf_pid
221*61046927SAndroid Build Coastguard Worker #define f_fd xf_fd
222*61046927SAndroid Build Coastguard Worker #define f_file xf_file
223*61046927SAndroid Build Coastguard Worker #endif
224*61046927SAndroid Build Coastguard Worker
225*61046927SAndroid Build Coastguard Worker #endif /* DETECT_OS_DRAGONFLY || DETECT_OS_FREEBSD */
226*61046927SAndroid Build Coastguard Worker
227*61046927SAndroid Build Coastguard Worker int
os_same_file_description(int fd1,int fd2)228*61046927SAndroid Build Coastguard Worker os_same_file_description(int fd1, int fd2)
229*61046927SAndroid Build Coastguard Worker {
230*61046927SAndroid Build Coastguard Worker #ifdef SYS_kcmp
231*61046927SAndroid Build Coastguard Worker pid_t pid = getpid();
232*61046927SAndroid Build Coastguard Worker #endif
233*61046927SAndroid Build Coastguard Worker
234*61046927SAndroid Build Coastguard Worker /* Same file descriptor trivially implies same file description */
235*61046927SAndroid Build Coastguard Worker if (fd1 == fd2)
236*61046927SAndroid Build Coastguard Worker return 0;
237*61046927SAndroid Build Coastguard Worker
238*61046927SAndroid Build Coastguard Worker #ifdef SYS_kcmp
239*61046927SAndroid Build Coastguard Worker return syscall(SYS_kcmp, pid, pid, KCMP_FILE, fd1, fd2);
240*61046927SAndroid Build Coastguard Worker #elif DETECT_OS_DRAGONFLY || DETECT_OS_FREEBSD
241*61046927SAndroid Build Coastguard Worker int mib[] = { CTL_KERN, KERN_FILE };
242*61046927SAndroid Build Coastguard Worker size_t len;
243*61046927SAndroid Build Coastguard Worker if (sysctl(mib, ARRAY_SIZE(mib), NULL, &len, NULL, 0))
244*61046927SAndroid Build Coastguard Worker return -1;
245*61046927SAndroid Build Coastguard Worker struct kinfo_file *kf = malloc(len);
246*61046927SAndroid Build Coastguard Worker if (sysctl(mib, ARRAY_SIZE(mib), kf, &len, NULL, 0))
247*61046927SAndroid Build Coastguard Worker return -1;
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker size_t count = len / sizeof(*kf);
250*61046927SAndroid Build Coastguard Worker pid_t pid = getpid();
251*61046927SAndroid Build Coastguard Worker kvaddr_t fd1_kfile = 0, fd2_kfile = 0;
252*61046927SAndroid Build Coastguard Worker for (size_t i = 0; i < count; i++) {
253*61046927SAndroid Build Coastguard Worker if (pid != kf[i].f_pid)
254*61046927SAndroid Build Coastguard Worker continue;
255*61046927SAndroid Build Coastguard Worker if (fd1 == kf[i].f_fd)
256*61046927SAndroid Build Coastguard Worker fd1_kfile = kf[i].f_file;
257*61046927SAndroid Build Coastguard Worker if (fd2 == kf[i].f_fd)
258*61046927SAndroid Build Coastguard Worker fd2_kfile = kf[i].f_file;
259*61046927SAndroid Build Coastguard Worker }
260*61046927SAndroid Build Coastguard Worker free(kf);
261*61046927SAndroid Build Coastguard Worker
262*61046927SAndroid Build Coastguard Worker if (fd1_kfile == 0 || fd2_kfile == 0)
263*61046927SAndroid Build Coastguard Worker return -1;
264*61046927SAndroid Build Coastguard Worker
265*61046927SAndroid Build Coastguard Worker return (fd1_kfile < fd2_kfile) | ((fd1_kfile > fd2_kfile) << 1);
266*61046927SAndroid Build Coastguard Worker #else
267*61046927SAndroid Build Coastguard Worker /* Otherwise we can't tell */
268*61046927SAndroid Build Coastguard Worker return -1;
269*61046927SAndroid Build Coastguard Worker #endif
270*61046927SAndroid Build Coastguard Worker }
271