Skip to contentSkip to conversation

dash test -w oddities

DISCUSSION Remi Broemeling 3 participants 7 messages Apr 30, 2008 – May 2, 2008

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw
Quoted 3 lines

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.

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 int
test_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 :)
____

#2 lore raw

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
____

#3 lore raw

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/sh isn'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

#4 lore raw

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/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

It 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.
____

#5 lore raw

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/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.)

This is largely considered a bug in bash, at least when invoked as /bin/sh.

-hpa

#6 lore raw

Re: euidaccess() vs non suid /bin/sh (Re: dash test -w oddities)

In reply to Oleg Verych
Quoted 4 lines

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

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
____