diff options
| author | Philipp Stephani | 2020-12-14 21:25:11 +0100 |
|---|---|---|
| committer | Philipp Stephani | 2021-04-10 20:37:29 +0200 |
| commit | 8a84f97abed548e4a254a9b855c3f79dac8c3d5d (patch) | |
| tree | ff11125ebe50e1772fbfb0336f156571aed0baef | |
| parent | 15122b31040f8945d0998510abd52c7735b36bc7 (diff) | |
| download | emacs-8a84f97abed548e4a254a9b855c3f79dac8c3d5d.tar.gz emacs-8a84f97abed548e4a254a9b855c3f79dac8c3d5d.zip | |
Read file in a loop if necessary.
This allows for short reads from 'emacs_read'.
* src/emacs.c (read_full): New helper function.
(load_seccomp): Use it.
| -rw-r--r-- | src/emacs.c | 50 |
1 files changed, 39 insertions, 11 deletions
diff --git a/src/emacs.c b/src/emacs.c index b956e9ca34b..8658b1886ed 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -967,6 +967,43 @@ emacs_seccomp (unsigned int operation, unsigned int flags, void *args) | |||
| 967 | #endif | 967 | #endif |
| 968 | } | 968 | } |
| 969 | 969 | ||
| 970 | /* Read SIZE bytes into BUFFER. Return the number of bytes read, or | ||
| 971 | -1 if reading failed altogether. */ | ||
| 972 | |||
| 973 | static ptrdiff_t | ||
| 974 | read_full (int fd, void *buffer, ptrdiff_t size) | ||
| 975 | { | ||
| 976 | enum | ||
| 977 | { | ||
| 978 | /* See MAX_RW_COUNT in sysdep.c. */ | ||
| 979 | #ifdef MAX_RW_COUNT | ||
| 980 | max_size = MAX_RW_COUNT | ||
| 981 | #else | ||
| 982 | max_size = INT_MAX >> 18 << 18 | ||
| 983 | #endif | ||
| 984 | }; | ||
| 985 | if (PTRDIFF_MAX < size || max_size < size) | ||
| 986 | { | ||
| 987 | errno = EFBIG; | ||
| 988 | return -1; | ||
| 989 | } | ||
| 990 | char *ptr = buffer; | ||
| 991 | ptrdiff_t read = 0; | ||
| 992 | while (size != 0) | ||
| 993 | { | ||
| 994 | ptrdiff_t n = emacs_read (fd, ptr, size); | ||
| 995 | if (n < 0) | ||
| 996 | return -1; | ||
| 997 | if (n == 0) | ||
| 998 | break; /* Avoid infinite loop on encountering EOF. */ | ||
| 999 | eassert (n <= size); | ||
| 1000 | size -= n; | ||
| 1001 | ptr += n; | ||
| 1002 | read += n; | ||
| 1003 | } | ||
| 1004 | return read; | ||
| 1005 | } | ||
| 1006 | |||
| 970 | /* Attempt to load Secure Computing filters from FILE. Return false | 1007 | /* Attempt to load Secure Computing filters from FILE. Return false |
| 971 | if that doesn't work for some reason. */ | 1008 | if that doesn't work for some reason. */ |
| 972 | 1009 | ||
| @@ -993,18 +1030,9 @@ load_seccomp (const char *file) | |||
| 993 | fprintf (stderr, "seccomp file %s is not regular\n", file); | 1030 | fprintf (stderr, "seccomp file %s is not regular\n", file); |
| 994 | goto out; | 1031 | goto out; |
| 995 | } | 1032 | } |
| 996 | enum | ||
| 997 | { | ||
| 998 | /* See MAX_RW_COUNT in sysdep.c. */ | ||
| 999 | #ifdef MAX_RW_COUNT | ||
| 1000 | max_read_size = MAX_RW_COUNT | ||
| 1001 | #else | ||
| 1002 | max_read_size = INT_MAX >> 18 << 18 | ||
| 1003 | #endif | ||
| 1004 | }; | ||
| 1005 | struct sock_fprog program; | 1033 | struct sock_fprog program; |
| 1006 | if (stat.st_size <= 0 || SIZE_MAX <= stat.st_size | 1034 | if (stat.st_size <= 0 || SIZE_MAX <= stat.st_size |
| 1007 | || PTRDIFF_MAX <= stat.st_size || max_read_size < stat.st_size | 1035 | || PTRDIFF_MAX <= stat.st_size |
| 1008 | || stat.st_size % sizeof *program.filter != 0) | 1036 | || stat.st_size % sizeof *program.filter != 0) |
| 1009 | { | 1037 | { |
| 1010 | fprintf (stderr, "seccomp filter %s has invalid size %ld\n", | 1038 | fprintf (stderr, "seccomp filter %s has invalid size %ld\n", |
| @@ -1026,7 +1054,7 @@ load_seccomp (const char *file) | |||
| 1026 | emacs_perror ("malloc"); | 1054 | emacs_perror ("malloc"); |
| 1027 | goto out; | 1055 | goto out; |
| 1028 | } | 1056 | } |
| 1029 | ptrdiff_t read = emacs_read (fd, buffer, size + 1); | 1057 | ptrdiff_t read = read_full (fd, buffer, size + 1); |
| 1030 | if (read < 0) | 1058 | if (read < 0) |
| 1031 | { | 1059 | { |
| 1032 | emacs_perror ("read"); | 1060 | emacs_perror ("read"); |