diff options
| author | Paul Eggert | 2013-01-17 21:12:08 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-01-17 21:12:08 -0800 |
| commit | 6772211202c57f0dc96e5725f882a2fa4ee98d2d (patch) | |
| tree | 7e2ca991fa357834552b26980ca392d6f982559e /src | |
| parent | 0eb8768885fab926acfae16d2fae8d39a72d8f35 (diff) | |
| download | emacs-6772211202c57f0dc96e5725f882a2fa4ee98d2d.tar.gz emacs-6772211202c57f0dc96e5725f882a2fa4ee98d2d.zip | |
Close a race when statting and reading files.
* fileio.c (Finsert_file_contents): Use open+fstat, not stat+open.
This avoids a race if the file is renamed between stat and open.
This race is not the problem originally noted in Bug#13149;
see <http://bugs.gnu.org/13149#73> and later messages in the thread.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 8 | ||||
| -rw-r--r-- | src/fileio.c | 44 |
2 files changed, 21 insertions, 31 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index c85e0a789ea..f53b9a70e97 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,11 @@ | |||
| 1 | 2013-01-17 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Close a race when statting and reading files (Bug#13149). | ||
| 4 | * fileio.c (Finsert_file_contents): Use open+fstat, not stat+open. | ||
| 5 | This avoids a race if the file is renamed between stat and open. | ||
| 6 | This race is not the problem originally noted in Bug#13149; | ||
| 7 | see <http://bugs.gnu.org/13149#73> and later messages in the thread. | ||
| 8 | |||
| 1 | 2013-01-17 Dmitry Antipov <dmantipov@yandex.ru> | 9 | 2013-01-17 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 10 | ||
| 3 | * lisp.h (toplevel): Add comment about using Lisp_Save_Value | 11 | * lisp.h (toplevel): Add comment about using Lisp_Save_Value |
diff --git a/src/fileio.c b/src/fileio.c index 8d711e8e6bf..41b8ae388d1 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -3492,7 +3492,6 @@ by calling `format-decode', which see. */) | |||
| 3492 | (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace) | 3492 | (Lisp_Object filename, Lisp_Object visit, Lisp_Object beg, Lisp_Object end, Lisp_Object replace) |
| 3493 | { | 3493 | { |
| 3494 | struct stat st; | 3494 | struct stat st; |
| 3495 | int file_status; | ||
| 3496 | EMACS_TIME mtime; | 3495 | EMACS_TIME mtime; |
| 3497 | int fd; | 3496 | int fd; |
| 3498 | ptrdiff_t inserted = 0; | 3497 | ptrdiff_t inserted = 0; |
| @@ -3554,26 +3553,9 @@ by calling `format-decode', which see. */) | |||
| 3554 | orig_filename = filename; | 3553 | orig_filename = filename; |
| 3555 | filename = ENCODE_FILE (filename); | 3554 | filename = ENCODE_FILE (filename); |
| 3556 | 3555 | ||
| 3557 | fd = -1; | 3556 | fd = emacs_open (SSDATA (filename), O_RDONLY, 0); |
| 3558 | 3557 | if (fd < 0) | |
| 3559 | #ifdef WINDOWSNT | ||
| 3560 | { | ||
| 3561 | Lisp_Object tem = Vw32_get_true_file_attributes; | ||
| 3562 | |||
| 3563 | /* Tell stat to use expensive method to get accurate info. */ | ||
| 3564 | Vw32_get_true_file_attributes = Qt; | ||
| 3565 | file_status = stat (SSDATA (filename), &st); | ||
| 3566 | Vw32_get_true_file_attributes = tem; | ||
| 3567 | } | ||
| 3568 | #else | ||
| 3569 | file_status = stat (SSDATA (filename), &st); | ||
| 3570 | #endif /* WINDOWSNT */ | ||
| 3571 | |||
| 3572 | if (file_status == 0) | ||
| 3573 | mtime = get_stat_mtime (&st); | ||
| 3574 | else | ||
| 3575 | { | 3558 | { |
| 3576 | badopen: | ||
| 3577 | save_errno = errno; | 3559 | save_errno = errno; |
| 3578 | if (NILP (visit)) | 3560 | if (NILP (visit)) |
| 3579 | report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); | 3561 | report_file_error ("Opening input file", Fcons (orig_filename, Qnil)); |
| @@ -3585,6 +3567,17 @@ by calling `format-decode', which see. */) | |||
| 3585 | goto notfound; | 3567 | goto notfound; |
| 3586 | } | 3568 | } |
| 3587 | 3569 | ||
| 3570 | /* Replacement should preserve point as it preserves markers. */ | ||
| 3571 | if (!NILP (replace)) | ||
| 3572 | record_unwind_protect (restore_point_unwind, Fpoint_marker ()); | ||
| 3573 | |||
| 3574 | record_unwind_protect (close_file_unwind, make_number (fd)); | ||
| 3575 | |||
| 3576 | if (fstat (fd, &st) != 0) | ||
| 3577 | report_file_error ("Getting input file status", | ||
| 3578 | Fcons (orig_filename, Qnil)); | ||
| 3579 | mtime = get_stat_mtime (&st); | ||
| 3580 | |||
| 3588 | /* This code will need to be changed in order to work on named | 3581 | /* This code will need to be changed in order to work on named |
| 3589 | pipes, and it's probably just not worth it. So we should at | 3582 | pipes, and it's probably just not worth it. So we should at |
| 3590 | least signal an error. */ | 3583 | least signal an error. */ |
| @@ -3600,17 +3593,6 @@ by calling `format-decode', which see. */) | |||
| 3600 | build_string ("not a regular file"), orig_filename); | 3593 | build_string ("not a regular file"), orig_filename); |
| 3601 | } | 3594 | } |
| 3602 | 3595 | ||
| 3603 | if (fd < 0) | ||
| 3604 | if ((fd = emacs_open (SSDATA (filename), O_RDONLY, 0)) < 0) | ||
| 3605 | goto badopen; | ||
| 3606 | |||
| 3607 | /* Replacement should preserve point as it preserves markers. */ | ||
| 3608 | if (!NILP (replace)) | ||
| 3609 | record_unwind_protect (restore_point_unwind, Fpoint_marker ()); | ||
| 3610 | |||
| 3611 | record_unwind_protect (close_file_unwind, make_number (fd)); | ||
| 3612 | |||
| 3613 | |||
| 3614 | if (!NILP (visit)) | 3596 | if (!NILP (visit)) |
| 3615 | { | 3597 | { |
| 3616 | if (!NILP (beg) || !NILP (end)) | 3598 | if (!NILP (beg) || !NILP (end)) |