Imported Upstream version 2.6.1
[platform/upstream/cryptsetup.git] / lib / utils.c
1 /*
2  * utils - miscellaneous device utilities for cryptsetup
3  *
4  * Copyright (C) 2004 Jana Saout <jana@saout.de>
5  * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
6  * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
7  * Copyright (C) 2009-2023 Milan Broz
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include <sys/mman.h>
27 #include <sys/resource.h>
28 #include <sys/stat.h>
29 #include <sys/utsname.h>
30
31 #include "internal.h"
32
33 size_t crypt_getpagesize(void)
34 {
35         long r = sysconf(_SC_PAGESIZE);
36         return r <= 0 ? DEFAULT_MEM_ALIGNMENT : (size_t)r;
37 }
38
39 unsigned crypt_cpusonline(void)
40 {
41         long r = sysconf(_SC_NPROCESSORS_ONLN);
42         return r < 0 ? 1 : r;
43 }
44
45 uint64_t crypt_getphysmemory_kb(void)
46 {
47         long pagesize, phys_pages;
48         uint64_t phys_memory_kb;
49
50         pagesize = sysconf(_SC_PAGESIZE);
51         phys_pages = sysconf(_SC_PHYS_PAGES);
52
53         if (pagesize < 0 || phys_pages < 0)
54                 return 0;
55
56         phys_memory_kb = pagesize / 1024;
57         phys_memory_kb *= phys_pages;
58
59         return phys_memory_kb;
60 }
61
62 void crypt_process_priority(struct crypt_device *cd, int *priority, bool raise)
63 {
64         int _priority, new_priority;
65
66         if (raise) {
67                 _priority = getpriority(PRIO_PROCESS, 0);
68                 if (_priority < 0)
69                         _priority = 0;
70                 if (priority)
71                         *priority = _priority;
72
73                 /*
74                  * Do not bother checking CAP_SYS_NICE as device activation
75                  * requires CAP_SYSADMIN later anyway.
76                  */
77                 if (getuid() || geteuid())
78                         new_priority = 0;
79                 else
80                         new_priority = -18;
81
82                 if (setpriority(PRIO_PROCESS, 0, new_priority))
83                         log_dbg(cd, "Cannot raise process priority.");
84         } else {
85                 _priority = priority ? *priority : 0;
86                 if (setpriority(PRIO_PROCESS, 0, _priority))
87                         log_dbg(cd, "Cannot reset process priority.");
88         }
89 }
90
91 /* Keyfile processing */
92
93 /*
94  * A simple call to lseek(3) might not be possible for some inputs (e.g.
95  * reading from a pipe), so this function instead reads of up to BUFSIZ bytes
96  * at a time until the specified number of bytes. It returns -1 on read error
97  * or when it reaches EOF before the requested number of bytes have been
98  * discarded.
99  */
100 static int keyfile_seek(int fd, uint64_t bytes)
101 {
102         char tmp[BUFSIZ];
103         size_t next_read;
104         ssize_t bytes_r;
105         off_t r;
106
107         r = lseek(fd, bytes, SEEK_CUR);
108         if (r > 0)
109                 return 0;
110         if (r < 0 && errno != ESPIPE)
111                 return -1;
112
113         while (bytes > 0) {
114                 /* figure out how much to read */
115                 next_read = bytes > sizeof(tmp) ? sizeof(tmp) : (size_t)bytes;
116
117                 bytes_r = read(fd, tmp, next_read);
118                 if (bytes_r < 0) {
119                         if (errno == EINTR)
120                                 continue;
121
122                         crypt_safe_memzero(tmp, sizeof(tmp));
123                         /* read error */
124                         return -1;
125                 }
126
127                 if (bytes_r == 0)
128                         /* EOF */
129                         break;
130
131                 bytes -= bytes_r;
132         }
133
134         crypt_safe_memzero(tmp, sizeof(tmp));
135         return bytes == 0 ? 0 : -1;
136 }
137
138 int crypt_keyfile_device_read(struct crypt_device *cd,  const char *keyfile,
139                               char **key, size_t *key_size_read,
140                               uint64_t keyfile_offset, size_t key_size,
141                               uint32_t flags)
142 {
143         int fd, regular_file, char_to_read = 0, char_read = 0, unlimited_read = 0;
144         int r = -EINVAL, newline;
145         char *pass = NULL;
146         size_t buflen, i;
147         uint64_t file_read_size;
148         struct stat st;
149
150         if (!key || !key_size_read)
151                 return -EINVAL;
152
153         *key = NULL;
154         *key_size_read = 0;
155
156         fd = keyfile ? open(keyfile, O_RDONLY) : STDIN_FILENO;
157         if (fd < 0) {
158                 log_err(cd, _("Failed to open key file."));
159                 return -EINVAL;
160         }
161
162         if (isatty(fd)) {
163                 log_err(cd, _("Cannot read keyfile from a terminal."));
164                 goto out;
165         }
166
167         /* If not requested otherwise, we limit input to prevent memory exhaustion */
168         if (key_size == 0) {
169                 key_size = DEFAULT_KEYFILE_SIZE_MAXKB * 1024 + 1;
170                 unlimited_read = 1;
171                 /* use 4k for buffer (page divisor but avoid huge pages) */
172                 buflen = 4096 - 16; /* sizeof(struct safe_allocation); */
173         } else
174                 buflen = key_size;
175
176         regular_file = 0;
177         if (keyfile) {
178                 if (stat(keyfile, &st) < 0) {
179                         log_err(cd, _("Failed to stat key file."));
180                         goto out;
181                 }
182                 if (S_ISREG(st.st_mode)) {
183                         regular_file = 1;
184                         file_read_size = (uint64_t)st.st_size;
185
186                         if (keyfile_offset > file_read_size) {
187                                 log_err(cd, _("Cannot seek to requested keyfile offset."));
188                                 goto out;
189                         }
190                         file_read_size -= keyfile_offset;
191
192                         /* known keyfile size, alloc it in one step */
193                         if (file_read_size >= (uint64_t)key_size)
194                                 buflen = key_size;
195                         else if (file_read_size)
196                                 buflen = file_read_size;
197                 }
198         }
199
200         pass = crypt_safe_alloc(buflen);
201         if (!pass) {
202                 log_err(cd, _("Out of memory while reading passphrase."));
203                 goto out;
204         }
205
206         /* Discard keyfile_offset bytes on input */
207         if (keyfile_offset && keyfile_seek(fd, keyfile_offset) < 0) {
208                 log_err(cd, _("Cannot seek to requested keyfile offset."));
209                 goto out;
210         }
211
212         for (i = 0, newline = 0; i < key_size; i += char_read) {
213                 if (i == buflen) {
214                         buflen += 4096;
215                         pass = crypt_safe_realloc(pass, buflen);
216                         if (!pass) {
217                                 log_err(cd, _("Out of memory while reading passphrase."));
218                                 r = -ENOMEM;
219                                 goto out;
220                         }
221                 }
222
223                 if (flags & CRYPT_KEYFILE_STOP_EOL) {
224                         /* If we should stop on newline, we must read the input
225                          * one character at the time. Otherwise we might end up
226                          * having read some bytes after the newline, which we
227                          * promised not to do.
228                          */
229                         char_to_read = 1;
230                 } else {
231                         /* char_to_read = min(key_size - i, buflen - i) */
232                         char_to_read = key_size < buflen ?
233                                 key_size - i : buflen - i;
234                 }
235                 char_read = read_buffer(fd, &pass[i], char_to_read);
236                 if (char_read < 0) {
237                         log_err(cd, _("Error reading passphrase."));
238                         r = -EPIPE;
239                         goto out;
240                 }
241
242                 if (char_read == 0)
243                         break;
244                 /* Stop on newline only if not requested read from keyfile */
245                 if ((flags & CRYPT_KEYFILE_STOP_EOL) && pass[i] == '\n') {
246                         newline = 1;
247                         pass[i] = '\0';
248                         break;
249                 }
250         }
251
252         /* Fail if piped input dies reading nothing */
253         if (!i && !regular_file && !newline) {
254                 log_err(cd, _("Nothing to read on input."));
255                 r = -EPIPE;
256                 goto out;
257         }
258
259         /* Fail if we exceeded internal default (no specified size) */
260         if (unlimited_read && i == key_size) {
261                 log_err(cd, _("Maximum keyfile size exceeded."));
262                 goto out;
263         }
264
265         if (!unlimited_read && i != key_size) {
266                 log_err(cd, _("Cannot read requested amount of data."));
267                 goto out;
268         }
269
270         *key = pass;
271         *key_size_read = i;
272         r = 0;
273 out:
274         if (fd != STDIN_FILENO)
275                 close(fd);
276
277         if (r)
278                 crypt_safe_free(pass);
279         return r;
280 }
281
282 int crypt_keyfile_read(struct crypt_device *cd,  const char *keyfile,
283                        char **key, size_t *key_size_read,
284                        size_t keyfile_offset, size_t keyfile_size_max,
285                        uint32_t flags)
286 {
287         return crypt_keyfile_device_read(cd, keyfile, key, key_size_read,
288                                          keyfile_offset, keyfile_size_max, flags);
289 }
290
291 int kernel_version(uint64_t *kversion)
292 {
293         struct utsname uts;
294         uint16_t maj, min, patch, rel;
295         int r = -EINVAL;
296
297         if (uname(&uts) < 0)
298                 return r;
299
300         if (sscanf(uts.release, "%" SCNu16  ".%" SCNu16 ".%" SCNu16 "-%" SCNu16,
301                    &maj, &min, &patch, &rel) == 4)
302                 r = 0;
303         else if (sscanf(uts.release,  "%" SCNu16 ".%" SCNu16 ".%" SCNu16,
304                         &maj, &min, &patch) == 3) {
305                 rel = 0;
306                 r = 0;
307         }
308
309         if (!r)
310                 *kversion = compact_version(maj, min, patch, rel);
311
312         return r;
313 }
314
315 bool crypt_string_in(const char *str, char **list, size_t list_size)
316 {
317         size_t i;
318
319         for (i = 0; *list && i < list_size; i++, list++)
320                 if (!strcmp(str, *list))
321                         return true;
322
323         return false;
324 }
325
326 /* compare two strings (allows NULL values) */
327 int crypt_strcmp(const char *a, const char *b)
328 {
329         if (!a && !b)
330                 return 0;
331         else if (!a || !b)
332                 return 1;
333         return strcmp(a, b);
334 }