diff options
| author | Philipp Stephani | 2016-03-31 23:10:40 +0200 |
|---|---|---|
| committer | John Wiegley | 2016-04-09 12:54:45 -0700 |
| commit | b57076929f0e904864e1457d5789f2fe6652fc84 (patch) | |
| tree | 7f2abba48a380899cfc6e164aa9914bc6dee5011 /src | |
| parent | 97211f3630d0f5b76a5416075f7c7182e1ee3abd (diff) | |
| download | emacs-b57076929f0e904864e1457d5789f2fe6652fc84.tar.gz emacs-b57076929f0e904864e1457d5789f2fe6652fc84.zip | |
Remove undefined behavior in OS X dumper.
Found by Address Sanitizer.
* src/unexmacosx.c (unexec_write): Use Mach virtual memory API to
avoid undefined behavior when reading arbitrary memory.
Diffstat (limited to 'src')
| -rw-r--r-- | src/unexmacosx.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/src/unexmacosx.c b/src/unexmacosx.c index 827eda56e08..bdacc8b540b 100644 --- a/src/unexmacosx.c +++ b/src/unexmacosx.c | |||
| @@ -103,9 +103,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 103 | #include <stdio.h> | 103 | #include <stdio.h> |
| 104 | #include <fcntl.h> | 104 | #include <fcntl.h> |
| 105 | #include <stdarg.h> | 105 | #include <stdarg.h> |
| 106 | #include <stdint.h> | ||
| 106 | #include <sys/types.h> | 107 | #include <sys/types.h> |
| 107 | #include <unistd.h> | 108 | #include <unistd.h> |
| 108 | #include <mach/mach.h> | 109 | #include <mach/mach.h> |
| 110 | #include <mach/vm_map.h> | ||
| 109 | #include <mach-o/loader.h> | 111 | #include <mach-o/loader.h> |
| 110 | #include <mach-o/reloc.h> | 112 | #include <mach-o/reloc.h> |
| 111 | #ifdef HAVE_MALLOC_MALLOC_H | 113 | #ifdef HAVE_MALLOC_MALLOC_H |
| @@ -217,10 +219,27 @@ unexec_read (void *dest, size_t n) | |||
| 217 | static int | 219 | static int |
| 218 | unexec_write (off_t dest, const void *src, size_t count) | 220 | unexec_write (off_t dest, const void *src, size_t count) |
| 219 | { | 221 | { |
| 222 | task_t task = mach_task_self(); | ||
| 223 | if (task == MACH_PORT_NULL || task == MACH_PORT_DEAD) | ||
| 224 | return false; | ||
| 225 | |||
| 220 | if (lseek (outfd, dest, SEEK_SET) != dest) | 226 | if (lseek (outfd, dest, SEEK_SET) != dest) |
| 221 | return 0; | 227 | return 0; |
| 222 | 228 | ||
| 223 | return write (outfd, src, count) == count; | 229 | /* We use the Mach virtual memory API to read our process memory |
| 230 | because using src directly would be undefined behavior and fails | ||
| 231 | under Address Sanitizer. */ | ||
| 232 | bool success = false; | ||
| 233 | vm_offset_t data; | ||
| 234 | mach_msg_type_number_t data_count; | ||
| 235 | if (vm_read (task, (uintptr_t) src, count, &data, &data_count) | ||
| 236 | == KERN_SUCCESS) | ||
| 237 | { | ||
| 238 | success = | ||
| 239 | write (outfd, (const void *) (uintptr_t) data, data_count) == count; | ||
| 240 | vm_deallocate (task, data, data_count); | ||
| 241 | } | ||
| 242 | return success; | ||
| 224 | } | 243 | } |
| 225 | 244 | ||
| 226 | /* Write COUNT bytes of zeros to outfd starting at offset DEST. | 245 | /* Write COUNT bytes of zeros to outfd starting at offset DEST. |