dash test -w oddities
Today I encountered some oddities using test -w as well as [ -w. The machine in question is an NFS-root (exported and mounted read-only) server running Ubuntu 8.04 LTS.
------
root@nexhost:~# mount rootfs on / type rootfs (rw) <snip non-relevant mounts> 192.168.10.60:/var/lib/tftpboot/netboot/default.r14599-amd64 on / type nfs (ro,relatime,vers=3,rsize=524288,wsize=524288,hard,nointr,nolock,proto=tcp,timeo=7,retrans=3,sec=sys,addr=192.168.10.60) <snip non-relevant mounts> ------
If I try using -w in bash, things work as expected:
------
root@nexhost:~# bash root@nexhost:~# [ -w / ] && echo Writable Root root@nexhost:~# test -w / && echo Writable Root root@nexhost:~# /usr/bin/[ -w / ] && echo Writable Root root@nexhost:~# /usr/bin/test -w / && echo Writable Root ------
However, if I try using -w in dash, the builtin does not seem to work as I would expect:
------
# [ -w / ] && echo Writable Root
Writable Root
# test -w / && echo Writable Root Writable Root # /usr/bin/[ -w / ] && echo Writable Root # /usr/bin/test -w / && echo Writable Root ------
I'm not sure if I am misunderstanding what is supposed to be happening with test/[, or if this is a bug in the dash built-ins, but I thought that I should at least mention it in case it is a bug.
Thanks.
Signature · 12 lines
Remi Broemeling Sr System Administrator Nexopia.com Inc. P: 780.444.1250 X435 F: 780.487.0376 E: [email protected] N: rbroemeling There are two major products that come out of Berkeley: LSD and UNIX. We don't believe this to be a coincidence. Jeremy S. Anderson
Quoted 3 lines
Today I encountered some oddities using
test -was well as[ -w. The machine in question is an NFS-root (exported and mounted read-only) server running Ubuntu 8.04 LTS.
important: you *are* root, right?
Some time ago i wanted to rewrite test, but due to "dash is in Ubuntu upstream" answer. i've stopped.
So, here it is, naive replacement of access() syscall (with crutches from GPLed bash). I've asked why it's needed and why euidaccess() from glibc wasn't used, especially in case of selinux stuff. But it seems, like dash fork of ash is just in bug-fixing mode.
#/bin/cc
/*
* Similar to what access(2) does, but uses the effective uid and gid.
* Doesn't make the mistake of telling root that any file is executable.
* Returns non-zero if the file is accessible.
*/
static inttest_st_mode(const struct stat64 *st, int mode)
{
int euid = geteuid();
if (euid == 0) {
/* Root can read or write any file. */
if (mode != X_OK)
return 1;[....]
#cc_end
In case you have no man page:
olecom@flower:~$ grep euidaccess </usr/include/unistd.h extern int euidaccess (__const char *__name, int __type) olecom@flower:~$
[]
Quoted 3 lines
There are two major products that come out of Berkeley: LSD and UNIX. We don't believe this to be a coincidence.
Jeremy S. Anderson
LSD && BSD actually :)
____
euidaccess() vs non suid /bin/sh (Re: dash test -w oddities)
Quoted 2 lines
I've asked why it's needed and why
euidaccess()from glibc wasn't used, especially in case of selinux stuff.
I wonder even more why access() syscall isn't a solution, because /bin/sh isn't set-uid by definition.
#/bin/cc glibc/sysdeps/posix/euidaccess.c
[...]
/* If we are not set-uid or set-gid, access does the same. */
return access (path, mode);[...]
#end_cc
____
Re: euidaccess() vs non suid /bin/sh (Re: dash test -w oddities)
Quoted 6 lines · Oleg Verych
Quoted 2 lines
I've asked why it's needed and why
euidaccess()from glibc wasn't used, especially in case of selinux stuff.I wonder even more why
access()syscall isn't a solution, because/bin/shisn't set-uid by definition.
Quoted 6 lines
#/bin/cc
glibc/sysdeps/posix/euidaccess.c
[...]/* If we are not set-uid or set-gid, access does the same. */ return access (path, mode);[...]
#end_cc
It might be run from a setuid program.
-hpa
Re: euidaccess() vs non suid /bin/sh (Re: dash test -w oddities)
Quoted 11 lines
Quoted 9 lines
I wonder even more why
access()syscall isn't a solution, because/bin/shisn't set-uid by definition.#/bin/cc
glibc/sysdeps/posix/euidaccess.c
[...]
/* If we are not set-uid or set-gid, access does the same. */ return access (path, mode);
[...]
#end_ccIt might be run from a setuid program.
Scripts with '#!/bin/sh' cannot be set-uid,
#man system (debian):
Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of func- tions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)
#end
Programs being designed to be set-uid should have proper setup for proper running any external command. No?
The call euidaccess() makes sense now, just asking to make clear this mess a bit.
____
Re: euidaccess() vs non suid /bin/sh (Re: dash test -w oddities)
Quoted 5 lines · Oleg Verych
Scripts with '#!/bin/sh' cannot be set-uid,
#man system (debian):
Quoted 8 lines
Do not use
system()from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of func- tions instead, but not execlp(3) or execvp(3).system()will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which/bin/shis bash version 2, since bash 2 drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)
This is largely considered a bug in bash, at least when invoked as /bin/sh.
-hpa
Re: euidaccess() vs non suid /bin/sh (Re: dash test -w oddities)
In reply to Oleg VerychQuoted 4 lines
I wonder even more why
access()syscall isn't a solution, because/bin/shisn't set-uid by definition.#/bin/cc
glibc/sysdeps/posix/euidaccess.c
Also why there's no such syscall, i wouldn't require all uid shuffling, isn't it?
#fs/open.c:sys_faccessat()
old_fsuid = current->fsuid;
old_fsgid = current->fsgid;
old_cap = current->cap_effective;
current->fsuid = current->uid;
current->fsgid = current->gid;#end
____