Linux命令之xargs的分析及隐患

时间:2023-03-10 05:41:51
Linux命令之xargs的分析及隐患

写一个main.c:

#include <stdio.h>

int main(){

printf("foo");

printf("bar");

return 0;

}

然后gcc编译为test.

然后在工作目录下建立两个目录:foo,bar

然后./test | xargs rm -rf

其实以上命令是删除不掉foo和bar的。

然后再来看以下

写一个main.c:

#include <stdio.h>

int main(){

printf("foo\n");

printf("bar\n");

return 0;

}

然后gcc编译为test.

然后在工作目录下建立两个目录:foo,bar

然后./test | xargs rm -rf

其实以上命令是能把foo bar删除了的。

然后再修改main.c

#include <stdio.h>

int main(){

printf("foo\nbar\n");

return 0;

}

以上的修改是也能删除foo和bar

然后再修改main.c

#include <stdio.h>

int main(){

printf("foo  bar");

return 0;

}

以上的修改是也能删除foo和bar

所以总结:

xargs是把整个输入流中的字符串遇到空格和换行符'\n'就截断为参数字符串(比如"foo bar"会被截断为两个字符串"foo"和"bar")传递给rm的,之前的foo和bar的输出没有换行符和空格,输出来就是“foobar”,由于工作目录没有建立foobar目录,当然就删除不掉了,所以也删不掉foo,bar目录。这样很显然是违背用户意愿了,如果工作目录下真存在foobar目录呢?万一这个目录很重要呢?那就悲剧了。

真相如下:

如果这回test是输出"foo bar"

有xargs的:(这个很明显能看到xargs的作用了)

./test | xargs strace rm -rf
execve("/bin/rm", ["rm", "-rf", "foo", "bar"], [/* 50 vars */]) = 0
brk(0)                                  = 0x17fc000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6e5fc7b000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=78756, ...}) = 0
mmap(NULL, 78756, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6e5fc67000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\30\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1815224, ...}) = 0
mmap(NULL, 3929304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6e5f69b000
mprotect(0x7f6e5f850000, 2097152, PROT_NONE) = 0
mmap(0x7f6e5fa50000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b5000) = 0x7f6e5fa50000
mmap(0x7f6e5fa56000, 17624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f6e5fa56000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6e5fc66000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6e5fc65000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6e5fc64000
arch_prctl(ARCH_SET_FS, 0x7f6e5fc65700) = 0
mprotect(0x7f6e5fa50000, 16384, PROT_READ) = 0
mprotect(0x60c000, 4096, PROT_READ)     = 0
mprotect(0x7f6e5fc7d000, 4096, PROT_READ) = 0
munmap(0x7f6e5fc67000, 78756)           = 0
brk(0)                                  = 0x17fc000
brk(0x181d000)                          = 0x181d000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=93101680, ...}) = 0
mmap(NULL, 93101680, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6e59dd1000
close(3)                                = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffd51c9478) = -1 ENOTTY (Inappropriate ioctl for device)
lstat("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
newfstatat(AT_FDCWD, "foo", {st_mode=S_IFDIR|0775, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "foo", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
fcntl(3, F_GETFD)                       = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
fcntl(3, F_GETFL)                       = 0x38800 (flags O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_NOFOLLOW)
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fcntl(3, F_DUPFD, 3)                    = 4
fcntl(4, F_GETFD)                       = 0
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
getdents(3, /* 2 entries */, 32768)     = 48
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
unlinkat(AT_FDCWD, "foo", AT_REMOVEDIR) = 0
close(4)                                = 0
newfstatat(AT_FDCWD, "bar", {st_mode=S_IFDIR|0775, st_size=4096, ...}, AT_SYMLINK_NOFOLLOW) = 0
openat(AT_FDCWD, "bar", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_DIRECTORY|O_NOFOLLOW) = 3
fcntl(3, F_GETFD)                       = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
fcntl(3, F_GETFL)                       = 0x38800 (flags O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_NOFOLLOW)
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fcntl(3, F_DUPFD, 3)                    = 4
fcntl(4, F_GETFD)                       = 0
fcntl(4, F_SETFD, FD_CLOEXEC)           = 0
getdents(3, /* 2 entries */, 32768)     = 48
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
unlinkat(AT_FDCWD, "bar", AT_REMOVEDIR) = 0
close(4)                                = 0
lseek(0, 0, SEEK_CUR)                   = 0
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?

没有xargs的:(由以下分析,很显然连“foo bar”这个参数都没有传递进去)

a@a:~/Downloads$ ./test |  strace rm -rf
execve("/bin/rm", ["rm", "-rf"], [/* 50 vars */]) = 0
brk(0)                                  = 0x17a9000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1bdbc08000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=78756, ...}) = 0
mmap(NULL, 78756, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f1bdbbf4000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240\30\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1815224, ...}) = 0
mmap(NULL, 3929304, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1bdb628000
mprotect(0x7f1bdb7dd000, 2097152, PROT_NONE) = 0
mmap(0x7f1bdb9dd000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b5000) = 0x7f1bdb9dd000
mmap(0x7f1bdb9e3000, 17624, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1bdb9e3000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1bdbbf3000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1bdbbf2000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1bdbbf1000
arch_prctl(ARCH_SET_FS, 0x7f1bdbbf2700) = 0
mprotect(0x7f1bdb9dd000, 16384, PROT_READ) = 0
mprotect(0x60c000, 4096, PROT_READ)     = 0
mprotect(0x7f1bdbc0a000, 4096, PROT_READ) = 0
munmap(0x7f1bdbbf4000, 78756)           = 0
brk(0)                                  = 0x17a9000
brk(0x17ca000)                          = 0x17ca000
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=93101680, ...}) = 0
mmap(NULL, 93101680, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f1bd5d5e000
close(3)                                = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, 0x7fffa591a788) = -1 ENOTTY (Inappropriate ioctl for device)
lseek(0, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
close(0)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?