1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef _UNISTD_H
17#error "Never include this file directly; instead, include <unistd.h>"
18#endif
19
20#include "fortify.h"
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
26#if defined(__FORTIFY_COMPILATION)
27
28#define __DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(what, fn) \
29    __DIAGNOSE_ERROR_IF((what) > FORTIFY_SSIZE_MAX, "in call to '" #fn "', '" #what "' must be <= FORTIFY_SSIZE_MAX")
30
31#define __DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(what, objsize, fn) \
32    __DIAGNOSE_ERROR_IF(__DIAGNOSE_UNEVALUATED_LT((objsize), (what)), \
33    "in call to '" #fn "', '" #what "' bytes overflows the given object")
34
35#define __DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos_val, index)  \
36    ((__DIAGNOSE_BOS_DYNAMIC_CHECK_IMPL_AND((bos_val), >=, (index), (bos_val) <= (FORTIFY_SSIZE_MAX)) && \
37    __builtin_constant_p(index) && (index) <= (FORTIFY_SSIZE_MAX)))
38
39char* __getcwd_chk(char*, size_t, size_t) ;
40
41ssize_t __pread_chk(int, void*, size_t, off_t, size_t);
42ssize_t __pread_real(int, void*, size_t, off_t) __DIAGNOSE_RENAME(pread);
43
44ssize_t __pwrite_chk(int, const void*, size_t, off_t, size_t);
45ssize_t __pwrite_real(int, const void*, size_t, off_t) __DIAGNOSE_RENAME(pwrite);
46
47ssize_t __read_chk(int, void*, size_t, size_t);
48ssize_t __write_chk(int, const void*, size_t, size_t);
49
50ssize_t __readlink_chk(const char*, char*, size_t, size_t);
51ssize_t __readlinkat_chk(int dirfd, const char*, char*, size_t, size_t);
52
53#define __DIAGNOSE_PREAD_PREFIX(x) __pread_ ## x
54#define __DIAGNOSE_PWRITE_PREFIX(x) __pwrite_ ## x
55
56__DIAGNOSE_FORTIFY_INLINE
57char* getcwd(char* const __DIAGNOSE_PASS_OBJECT_SIZE buf, size_t size)
58__DIAGNOSE_OVERLOAD
59__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(size, __DIAGNOSE_BOS(buf), getcwd)
60{
61#ifdef __FORTIFY_RUNTIME
62    size_t bos = __DIAGNOSE_BOS(buf);
63
64    if (!__DIAGNOSE_BOS_TRIVIALLY_GE(bos, size)) {
65        return __getcwd_chk(buf, size, bos);
66    }
67#endif
68    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(getcwd)(buf, size);
69}
70
71__DIAGNOSE_FORTIFY_INLINE
72ssize_t pread(int fd, void* const __DIAGNOSE_PASS_OBJECT_SIZE0 buf, size_t count, off_t offset)
73__DIAGNOSE_OVERLOAD
74__DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(count, pread)
75__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(count, __DIAGNOSE_BOS0(buf), pread)
76{
77#ifdef __FORTIFY_RUNTIME
78    size_t bos = __DIAGNOSE_BOS0(buf);
79
80    if (!__DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos, count)) {
81        return __DIAGNOSE_PREAD_PREFIX(chk)(fd, buf, count, offset, bos);
82    }
83#endif
84    return __DIAGNOSE_PREAD_PREFIX(real)(fd, buf, count, offset);
85}
86
87__DIAGNOSE_FORTIFY_INLINE
88ssize_t pwrite(int fd, const void* const __DIAGNOSE_PASS_OBJECT_SIZE0 buf, size_t count, off_t offset)
89__DIAGNOSE_OVERLOAD
90__DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(count, pwrite)
91__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(count, __DIAGNOSE_BOS0(buf), pwrite)
92{
93#ifdef __FORTIFY_RUNTIME
94    size_t bos = __DIAGNOSE_BOS0(buf);
95
96    if (!__DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos, count)) {
97        return __DIAGNOSE_PWRITE_PREFIX(chk)(fd, buf, count, offset, bos);
98    }
99#endif
100    return __DIAGNOSE_PWRITE_PREFIX(real)(fd, buf, count, offset);
101}
102
103__DIAGNOSE_FORTIFY_INLINE
104ssize_t read(int fd, void* const __DIAGNOSE_PASS_OBJECT_SIZE0 buf, size_t count)
105__DIAGNOSE_OVERLOAD
106__DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(count, read)
107__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(count, __DIAGNOSE_BOS0(buf), read)
108{
109#ifdef __FORTIFY_RUNTIME
110    size_t bos = __DIAGNOSE_BOS0(buf);
111
112    if (!__DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos, count)) {
113        return __read_chk(fd, buf, count, bos);
114    }
115#endif
116    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(read)(fd, buf, count);
117}
118
119__DIAGNOSE_FORTIFY_INLINE
120ssize_t write(int fd, const void* const __DIAGNOSE_PASS_OBJECT_SIZE0 buf, size_t count)
121__DIAGNOSE_OVERLOAD
122__DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(count, write)
123__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(count, __DIAGNOSE_BOS0(buf), write)
124{
125#ifdef __FORTIFY_RUNTIME
126    size_t bos = __DIAGNOSE_BOS0(buf);
127
128    if (!__DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos, count)) {
129        return __write_chk(fd, buf, count, bos);
130    }
131#endif
132    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(write)(fd, buf, count);
133}
134
135__DIAGNOSE_FORTIFY_INLINE
136ssize_t readlink(const char* path, char* const __DIAGNOSE_PASS_OBJECT_SIZE buf, size_t size)
137__DIAGNOSE_OVERLOAD
138__DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(size, readlink)
139__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(size, __DIAGNOSE_BOS(buf), readlink)
140{
141#ifdef __FORTIFY_RUNTIME
142    size_t bos = __DIAGNOSE_BOS(buf);
143
144    if (!__DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos, size)) {
145        return __readlink_chk(path, buf, size, bos);
146    }
147#endif
148    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(readlink)(path, buf, size);
149}
150
151__DIAGNOSE_FORTIFY_INLINE
152ssize_t readlinkat(int dirfd, const char* path, char* const __DIAGNOSE_PASS_OBJECT_SIZE buf, size_t size)
153__DIAGNOSE_OVERLOAD
154__DIAGNOSE_ERROR_IF_OVERFLOWS_SSIZET(size, readlinkat)
155__DIAGNOSE_ERROR_IF_OVERFLOWS_OBJECTSIZE(size, __DIAGNOSE_BOS(buf), readlinkat)
156{
157#ifdef __FORTIFY_RUNTIME
158    size_t bos = __DIAGNOSE_BOS(buf);
159
160    if (!__DIAGNOSE_BOS_TRIVIALLY_GE_NO_OVERFLOW(bos, size)) {
161        return __readlinkat_chk(dirfd, path, buf, size, bos);
162    }
163#endif
164    return __DIAGNOSE_CALL_BYPASSING_FORTIFY(readlinkat)(dirfd, path, buf, size);
165}
166
167#endif // defined(__FORTIFY_COMPILATION)
168
169#ifdef __cplusplus
170}
171#endif