shell nào sẽ sudo sử dụng để thực thi script shell mà không có dòng shebang


7

Môi trường của tôi là Ubuntu 12.04 LTS và sudophiên bản là 1.8.3p1.

Đầu tiên tôi đăng nhập như một người dùng bình thường:

$ whoami
fin

$ cat /etc/passwd | grep -i "root\|fin"
root:x:0:0:root:/root:/bin/bash
fin:x:1000:1000:This is a normal user:/home/fin:/bin/bash

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash

$ ls -l /bin/bash
-rwxr-xr-x 1 root root 920788 Apr  3  2012 /bin/bash

$ echo $SHELL
/bin/bash

$ ps | grep "$$" | awk '{ print $4 }'
bash

$ ls -l ./test.sh
-rwxr-xr-x 1 fin fin 37 Sep 27 16:46 test.sh

$ cat ./test.sh
ps | grep "$$" | awk '{ print $4 }'

$ ./test.sh
bash

$ sudo ./test.sh
sh

Tôi cho rằng đầu ra cuối cùng cũng phải là bash/etc/passwdcho thấy rằng việc sử dụng root bash, tôi có thiếu điểm sudonào không?

Câu trả lời:


12

Nó sử dụng _PATH_BSHELLnhư execvp()trên Linux được định nghĩa như /bin/shtrong /usr/include/paths.h. Điều đó sẽ giống như khi được thực hiện với envhoặc find -execví dụ.

Nó chắc chắn không nên sử dụng shell đăng nhập của người dùng. Thực tế mà bạn đang thấy bashở trên là bởi vì nó bash(vỏ bạn nhập dòng lệnh đó) cố gắng thực thi nó và khi nó nhận được ENOEXECmã lỗi từ execvenó quyết định tự mình giải thích nó (trong shchế độ tương thích).


Cảm ơn câu trả lời của bạn, vì vậy nó phụ thuộc vào việc thực hiện sudo để quyết định sử dụng shhay phân tích cú pháp /etc/passwdkhi nhận được ENOEXEClỗi?
layka

Không, sudosẽ không sử dụng shell đăng nhập của người dùng trừ khi bạn nói với nó bằng cách nói với nó rằng bạn muốn truyền cho nó một dòng lệnh để diễn giải bằng shell (với -s) trái ngược với lệnh thực thi. Nếu một lệnh để thực thi, nó sẽ hoạt động như thế execvp, giống như hệ thống có nghĩa là thực thi các lệnh.
Stéphane Chazelas

@Stephane Chazelas: Tôi nghĩ nó không có nghĩa là hệ thống để chạy lệnh. sudoluôn luôn thiết lập môi trường thực thi của nó trước khi gọi đến execve(). Nếu bạn không vượt qua -s, sudo sẽ sử dụng _PATH_BSHELL.
cuonglm

@Gnouc, Có, sudo sẽ sử dụng _PATH_BSHELL giống như hệ thống hiện tại (trong execvp (), env, find, vi hầu hết các shell ...), nó chỉ xảy ra để thực hiện phiên bản riêng của nó execvp(). Nó cũng có thể sử dụng _PATH_BSHELL với -s nếu thực thi $SHELLtrả về ENOEXEC. Xem bình luận của tôi để câu trả lời của bạn để biết thêm chi tiết.
Stéphane Chazelas

5

Vì bạn không sử dụng -stùy chọn, nên sudosẽ sử dụng _PATH_BSHELL(được xác định trong /usr/include/paths.hUbuntu 12.04 LTS) để thiết lập $SHELLchạy. Tìm kiếm sudomã nguồn:

/* Stash user's shell for use with the -s flag; don't pass to plugin. */
    if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') {
    ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_BSHELL;
    }

Nếu bạn sử dụng -stùy chọn, sudosẽ sử dụng $SHELLthay vì _PATH_BSHELL:

$ cat ./test.sh
ps | grep "$$" | awk '{ print $4 }'

$ ./test.sh
bash

$ sudo -s ./test.sh
bash

1
Lưu ý rằng điều -sđó không có nghĩa là tập lệnh sẽ được diễn giải bởi $SHELL, nó chỉ có nghĩa là (giả sử bạn đã được ủy quyền sử dụng $SHELLlàm người dùng đích), lệnh được bắt đầu như $SHELL -c ./test.sh. Shell thích bash, yashhoặc ksh93có thể chọn giải thích các tập lệnh không có tiếng với bản sao của chính họ, những người khác sẽ không và sẽ gọi hệ thống shthay thế.
Stéphane Chazelas

Nói cách khác, đó không phải là $ SHELL thay vì _PATH_BSHELL , đó là exec($SHELL, "-c", "./test.sh")vô điều kiện thay vì if (exec("./test.sh") == ENOEXEC) exec(_PATH_BSHELL, "./test.sh")(mã giả).
Stéphane Chazelas

4

Nhân chỉ có thể chạy hình ảnh thực thi nhị phân. Vậy làm thế nào để script được chạy? Rốt cuộc, tôi có thể gõ my_script_without_shebangtại dấu nhắc shell và tôi không gặp ENOEXEClỗi. Thực thi tập lệnh được thực hiện không phải bởi kernel, mà bằng shell. Mã exec trong shell thường trông giống như:

/* try to run the program */
execl(program, basename(program), (char *)0);

/* the exec failed -- maybe it is a shell script without shebang? */
if (errno == ENOEXEC)
    execl ("/bin/sh", "sh", "-c", program, (char *)0);

Bạn có thể xác minh rằng với việc truy tìm tập lệnh shell giả mà không có shebang:

cat > /tmp/foo.sh <<EOF
echo
EOF

chmod u+x /tmp/foo.sh

strace /tmp/foo.sh 2>&1 | grep exec
execve("/tmp/foo.sh", ["/tmp/foo.sh"], [/* 28 vars */]) = -1 ENOEXEC (Exec format error)

Vì vậy, sau đó, quá trình thực thi như Stephane đã mô tả - shell mặc định được sử dụng (trong đoạn mã trên được mã hóa cứng). Câu hỏi thường gặp về UNIX tốt đẹp này có thể trả lời nhiều hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.