aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbb/Config.in10
-rw-r--r--libbb/copy_file.c18
2 files changed, 19 insertions, 9 deletions
diff --git a/libbb/Config.in b/libbb/Config.in
index a572775c9..9b616d1af 100644
--- a/libbb/Config.in
+++ b/libbb/Config.in
@@ -114,6 +114,16 @@ config FEATURE_EDITING_ASK_TERMINAL
114 correctly, or want to save on code size (about 300 bytes), 114 correctly, or want to save on code size (about 300 bytes),
115 then do not turn this option on. 115 then do not turn this option on.
116 116
117config FEATURE_NON_POSIX_CP
118 bool "Non-POSIX, but safer, copying to special nodes"
119 default y
120 help
121 With this option, "cp file symlink" will delete symlink
122 and create a regular file. This does not conform to POSIX,
123 but prevents a symlink attack.
124 Similarly, "cp file device" will not send file's data
125 to the device.
126
117config FEATURE_VERBOSE_CP_MESSAGE 127config FEATURE_VERBOSE_CP_MESSAGE
118 bool "Give more precise messages when copy fails (cp, mv etc)" 128 bool "Give more precise messages when copy fails (cp, mv etc)"
119 default n 129 default n
diff --git a/libbb/copy_file.c b/libbb/copy_file.c
index d804eccfa..4d2f17aa5 100644
--- a/libbb/copy_file.c
+++ b/libbb/copy_file.c
@@ -8,9 +8,10 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 * 9 *
10 */ 10 */
11
12#include "libbb.h" 11#include "libbb.h"
13 12
13// FEATURE_NON_POSIX_CP:
14//
14// POSIX: if exists and -i, ask (w/o -i assume yes). 15// POSIX: if exists and -i, ask (w/o -i assume yes).
15// Then open w/o EXCL (yes, not unlink!). 16// Then open w/o EXCL (yes, not unlink!).
16// If open still fails and -f, try unlink, then try open again. 17// If open still fails and -f, try unlink, then try open again.
@@ -23,22 +24,21 @@
23// NB: we have special code which still allows for "cp file /dev/node" 24// NB: we have special code which still allows for "cp file /dev/node"
24// to work POSIX-ly (the only realistic case where it makes sense) 25// to work POSIX-ly (the only realistic case where it makes sense)
25 26
26#define DO_POSIX_CP 0 /* 1 - POSIX behavior, 0 - safe behavior */
27
28// errno must be set to relevant value ("why we cannot create dest?") 27// errno must be set to relevant value ("why we cannot create dest?")
29// for POSIX mode to give reasonable error message 28// for POSIX mode to give reasonable error message
30static int ask_and_unlink(const char *dest, int flags) 29static int ask_and_unlink(const char *dest, int flags)
31{ 30{
32 int e = errno; 31 int e = errno;
33#if DO_POSIX_CP 32#if !ENABLE_FEATURE_NON_POSIX_CP
34 if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) { 33 if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) {
35 // Either it exists, or the *path* doesnt exist 34 // Either it exists, or the *path* doesnt exist
36 bb_perror_msg("cannot create '%s'", dest); 35 bb_perror_msg("cannot create '%s'", dest);
37 return -1; 36 return -1;
38 } 37 }
39#endif 38#endif
40 // If !DO_POSIX_CP, act as if -f is always in effect - we don't want 39 // If ENABLE_FEATURE_NON_POSIX_CP, act as if -f is always in effect
41 // "cannot create" msg, we want unlink to be done (silently unless -i). 40 // - we don't want "cannot create" msg, we want unlink to be done
41 // (silently unless -i).
42 42
43 // TODO: maybe we should do it only if ctty is present? 43 // TODO: maybe we should do it only if ctty is present?
44 if (flags & FILEUTILS_INTERACTIVE) { 44 if (flags & FILEUTILS_INTERACTIVE) {
@@ -279,10 +279,10 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
279 * non-interactive cp. NB: it is still racy 279 * non-interactive cp. NB: it is still racy
280 * for "cp file /home/bad_user/file" case 280 * for "cp file /home/bad_user/file" case
281 * (user can rm file and create a link to /etc/passwd) */ 281 * (user can rm file and create a link to /etc/passwd) */
282 if (DO_POSIX_CP 282 if (!ENABLE_FEATURE_NON_POSIX_CP
283 || (dest_exists 283 || (dest_exists
284 && !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE)) 284 && !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE))
285 && !S_ISLNK(dest_stat.st_mode)) 285 && !S_ISLNK(dest_stat.st_mode))
286 ) { 286 ) {
287 dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode); 287 dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode);
288 } else /* safe way: */ 288 } else /* safe way: */