Claim that /zip itself is user-modifiable

This is in line with what I have learned about the TOCTOU stuff
regarding ape executables. If there is ever a check for whether
we are running in a secure set-id context, this can be disabled
by that check.

Adds basic sanity test for zipos stat as well.
This commit is contained in:
Jōshin 2023-12-17 12:31:37 -05:00
parent 77facc4f7b
commit f0971b6909
No known key found for this signature in database
2 changed files with 20 additions and 0 deletions

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/stat.h"
#include "libc/intrin/atomic.h"
@ -34,6 +35,12 @@ int __zipos_stat_impl(struct Zipos *zipos, size_t cf, struct stat *st) {
if (cf == ZIPOS_SYNTHETIC_DIRECTORY) {
st->st_mode = S_IFDIR | (0555 & ~atomic_load_explicit(
&__umask, memory_order_acquire));
/* report that /zip is user-modifiable to clarify to programs that check
transitive writability of a secure file like doas.conf. at this time,
doas itself does not actually do this check (it only checks the file)
but it probably ought to. */
st->st_uid = getuid();
st->st_mode |= S_IWUSR;
} else {
lf = GetZipCfileOffset(zipos->map + cf);
st->st_mode = GetZipCfileMode(zipos->map + cf);

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/sysv/consts/s.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/mem/gc.h"
@ -113,6 +114,18 @@ TEST(zipos, lseek) {
EXPECT_SYS(0, 0, close(3));
}
TEST(zipos, stat) {
struct stat st;
umask(0777);
ASSERT_SYS(0, 0, stat("/zip", &st));
EXPECT_EQ(getuid(), st.st_uid);
EXPECT_TRUE(S_ISDIR(st.st_mode));
EXPECT_TRUE((st.st_mode & S_IWUSR) != 0);
ASSERT_SYS(0, 0, stat("/zip/libc/testlib/hyperion.txt", &st));
EXPECT_EQ(0, st.st_uid);
EXPECT_EQ(0100644, st.st_mode);
}
TEST(zipos, closeAfterVfork) {
ASSERT_SYS(0, 3, open("/zip/libc/testlib/hyperion.txt", O_RDONLY));
SPAWN(vfork);