cp: by popular demand, make it POSIX compliant (but less safe)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
09e63bb81f
commit
2d7b5bfa9b
@ -114,6 +114,16 @@ config FEATURE_EDITING_ASK_TERMINAL
|
|||||||
correctly, or want to save on code size (about 300 bytes),
|
correctly, or want to save on code size (about 300 bytes),
|
||||||
then do not turn this option on.
|
then do not turn this option on.
|
||||||
|
|
||||||
|
config FEATURE_NON_POSIX_CP
|
||||||
|
bool "Non-POSIX, but safer, copying to special nodes"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
With this option, "cp file symlink" will delete symlink
|
||||||
|
and create a regular file. This does not conform to POSIX,
|
||||||
|
but prevents a symlink attack.
|
||||||
|
Similarly, "cp file device" will not send file's data
|
||||||
|
to the device.
|
||||||
|
|
||||||
config FEATURE_VERBOSE_CP_MESSAGE
|
config FEATURE_VERBOSE_CP_MESSAGE
|
||||||
bool "Give more precise messages when copy fails (cp, mv etc)"
|
bool "Give more precise messages when copy fails (cp, mv etc)"
|
||||||
default n
|
default n
|
||||||
|
@ -8,9 +8,10 @@
|
|||||||
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
|
// FEATURE_NON_POSIX_CP:
|
||||||
|
//
|
||||||
// POSIX: if exists and -i, ask (w/o -i assume yes).
|
// POSIX: if exists and -i, ask (w/o -i assume yes).
|
||||||
// Then open w/o EXCL (yes, not unlink!).
|
// Then open w/o EXCL (yes, not unlink!).
|
||||||
// If open still fails and -f, try unlink, then try open again.
|
// If open still fails and -f, try unlink, then try open again.
|
||||||
@ -23,22 +24,21 @@
|
|||||||
// NB: we have special code which still allows for "cp file /dev/node"
|
// NB: we have special code which still allows for "cp file /dev/node"
|
||||||
// to work POSIX-ly (the only realistic case where it makes sense)
|
// to work POSIX-ly (the only realistic case where it makes sense)
|
||||||
|
|
||||||
#define DO_POSIX_CP 0 /* 1 - POSIX behavior, 0 - safe behavior */
|
|
||||||
|
|
||||||
// errno must be set to relevant value ("why we cannot create dest?")
|
// errno must be set to relevant value ("why we cannot create dest?")
|
||||||
// for POSIX mode to give reasonable error message
|
// for POSIX mode to give reasonable error message
|
||||||
static int ask_and_unlink(const char *dest, int flags)
|
static int ask_and_unlink(const char *dest, int flags)
|
||||||
{
|
{
|
||||||
int e = errno;
|
int e = errno;
|
||||||
#if DO_POSIX_CP
|
#if !ENABLE_FEATURE_NON_POSIX_CP
|
||||||
if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) {
|
if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) {
|
||||||
// Either it exists, or the *path* doesnt exist
|
// Either it exists, or the *path* doesnt exist
|
||||||
bb_perror_msg("cannot create '%s'", dest);
|
bb_perror_msg("cannot create '%s'", dest);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// If !DO_POSIX_CP, act as if -f is always in effect - we don't want
|
// If ENABLE_FEATURE_NON_POSIX_CP, act as if -f is always in effect
|
||||||
// "cannot create" msg, we want unlink to be done (silently unless -i).
|
// - we don't want "cannot create" msg, we want unlink to be done
|
||||||
|
// (silently unless -i).
|
||||||
|
|
||||||
// TODO: maybe we should do it only if ctty is present?
|
// TODO: maybe we should do it only if ctty is present?
|
||||||
if (flags & FILEUTILS_INTERACTIVE) {
|
if (flags & FILEUTILS_INTERACTIVE) {
|
||||||
@ -279,10 +279,10 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags)
|
|||||||
* non-interactive cp. NB: it is still racy
|
* non-interactive cp. NB: it is still racy
|
||||||
* for "cp file /home/bad_user/file" case
|
* for "cp file /home/bad_user/file" case
|
||||||
* (user can rm file and create a link to /etc/passwd) */
|
* (user can rm file and create a link to /etc/passwd) */
|
||||||
if (DO_POSIX_CP
|
if (!ENABLE_FEATURE_NON_POSIX_CP
|
||||||
|| (dest_exists
|
|| (dest_exists
|
||||||
&& !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE))
|
&& !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE))
|
||||||
&& !S_ISLNK(dest_stat.st_mode))
|
&& !S_ISLNK(dest_stat.st_mode))
|
||||||
) {
|
) {
|
||||||
dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode);
|
dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode);
|
||||||
} else /* safe way: */
|
} else /* safe way: */
|
||||||
|
Loading…
Reference in New Issue
Block a user