- simplify code

- remove any 'permission checks' via geteuid() - with upcoming
  security models these might not match the model any more
- this also fixes a bug where ntp_adjtime() was denied (EPERM)
  even though only a legit read status was performed
This commit is contained in:
kardel 2006-10-07 20:02:01 +00:00
parent 5a0a4d9df3
commit 403d759108
4 changed files with 53 additions and 130 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: adjtime.c,v 1.7 2006/03/09 23:44:43 christos Exp $ */ /* $NetBSD: adjtime.c,v 1.8 2006/10/07 20:02:01 kardel Exp $ */
/* /*
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: adjtime.c,v 1.7 2006/03/09 23:44:43 christos Exp $"); __RCSID("$NetBSD: adjtime.c,v 1.8 2006/10/07 20:02:01 kardel Exp $");
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include "namespace.h" #include "namespace.h"
@ -61,16 +61,14 @@ adjtime(delta, olddelta)
struct timeval *olddelta; struct timeval *olddelta;
{ {
struct clockctl_adjtime args; struct clockctl_adjtime args;
int error;
quad_t q; quad_t q;
int rv; int rv;
/* /*
* if __clockctl_fd == -1, then this is not our first time, * we always attempt the syscall first and switch to
* and we know root is the calling user. We use the system call * clockctl if that fails with EPERM
*/ */
if (__clockctl_fd == -1) { if (__clockctl_fd == -1) {
try_syscall:
q = __syscall((quad_t)SYS_adjtime, delta, olddelta); q = __syscall((quad_t)SYS_adjtime, delta, olddelta);
if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t) if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t)
|| /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN) || /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN)
@ -79,38 +77,22 @@ try_syscall:
rv = (int)((u_quad_t)q >> 32); rv = (int)((u_quad_t)q >> 32);
/* /*
* If credentials changed from root to an unprivilegied * try via clockctl if the call fails with EPERM
* user, and we already had __clockctl_fd = -1, then we
* tried the system call as a non root user, it failed
* with EPERM, and we will try clockctl.
*/ */
if (rv != -1 || errno != EPERM) if (rv != -1 || errno != EPERM)
return rv; return rv;
__clockctl_fd = -2;
}
/*
* If __clockctl_fd = -2 then this is our first time here,
* or credentials have changed (the calling process dropped root
* root privilege). Check if root is the calling user. If it is,
* we try the system call, if it is not, we try clockctl.
*/
if (__clockctl_fd == -2) {
/*
* Root always uses the syscall
*/
if (geteuid() == 0) {
__clockctl_fd = -1;
goto try_syscall;
}
/* /*
* If this fails, it means that we are not root * If this fails, it means that we are not root
* and we cannot open clockctl. This is a failure. * and we cannot open clockctl. This is a failure.
*/ */
__clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0); __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0);
if (__clockctl_fd == -1) if (__clockctl_fd == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1; return -1;
}
(void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC); (void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC);
} }
@ -120,7 +102,5 @@ try_syscall:
*/ */
args.delta = delta; args.delta = delta;
args.olddelta = olddelta; args.olddelta = olddelta;
error = ioctl(__clockctl_fd, CLOCKCTL_ADJTIME, &args); return ioctl(__clockctl_fd, CLOCKCTL_ADJTIME, &args);
return error;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: clock_settime.c,v 1.7 2006/03/09 23:44:43 christos Exp $ */ /* $NetBSD: clock_settime.c,v 1.8 2006/10/07 20:02:01 kardel Exp $ */
/* /*
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: clock_settime.c,v 1.7 2006/03/09 23:44:43 christos Exp $"); __RCSID("$NetBSD: clock_settime.c,v 1.8 2006/10/07 20:02:01 kardel Exp $");
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include "namespace.h" #include "namespace.h"
@ -63,16 +63,14 @@ clock_settime(clock_id, tp)
const struct timespec *tp; const struct timespec *tp;
{ {
struct clockctl_clock_settime args; struct clockctl_clock_settime args;
int error;
quad_t q; quad_t q;
int rv; int rv;
/* /*
* if __clockctl_fd == -1, then this is not our first time, * always try the syscall first and attempt to switch to
* and we know root is the calling user. We use the system call * clockctl if that fails.
*/ */
if (__clockctl_fd == -1) { if (__clockctl_fd == -1) {
try_syscall:
q = __syscall((quad_t)SYS_clock_settime, clock_id, tp); q = __syscall((quad_t)SYS_clock_settime, clock_id, tp);
if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t) if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t)
|| /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN) || /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN)
@ -81,38 +79,22 @@ try_syscall:
rv = (int)((u_quad_t)q >> 32); rv = (int)((u_quad_t)q >> 32);
/* /*
* If credentials changed from root to an unprivilegied * return unless we failed with EPERM
* user, and we already had __clockctl_fd = -1, then we
* tried the system call as a non root user, it failed
* with EPERM, and we will try clockctl.
*/ */
if (rv != -1 || errno != EPERM) if (rv != -1 || errno != EPERM)
return rv; return rv;
__clockctl_fd = -2;
}
/*
* If __clockctl_fd = -2 then this is our first time here,
* or credentials have changed (the calling process dropped root
* root privilege). Check if root is the calling user. If it is,
* we try the system call, if it is not, we try clockctl.
*/
if (__clockctl_fd == -2) {
/*
* Root always uses the syscall
*/
if (geteuid() == 0) {
__clockctl_fd = -1;
goto try_syscall;
}
/* /*
* If this fails, it means that we are not root * If this fails, it means that we are not root
* and we cannot open clockctl. This is a failure. * and we cannot open clockctl. This is a failure.
*/ */
__clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0); __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0);
if (__clockctl_fd == -1) if (__clockctl_fd == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1; return -1;
}
(void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC); (void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC);
} }
@ -122,7 +104,5 @@ try_syscall:
*/ */
args.clock_id = clock_id; args.clock_id = clock_id;
args.tp = tp; args.tp = tp;
error = ioctl(__clockctl_fd, CLOCKCTL_CLOCK_SETTIME, &args); return ioctl(__clockctl_fd, CLOCKCTL_CLOCK_SETTIME, &args);
return error;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: ntp_adjtime.c,v 1.7 2006/03/09 23:44:43 christos Exp $ */ /* $NetBSD: ntp_adjtime.c,v 1.8 2006/10/07 20:02:01 kardel Exp $ */
/* /*
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: ntp_adjtime.c,v 1.7 2006/03/09 23:44:43 christos Exp $"); __RCSID("$NetBSD: ntp_adjtime.c,v 1.8 2006/10/07 20:02:01 kardel Exp $");
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include "namespace.h" #include "namespace.h"
@ -70,11 +70,12 @@ ntp_adjtime(tp)
int rv; int rv;
/* /*
* if __clockctl_fd == -1, then this is not our first time, * we always attempt to use the syscall unless we had to
* and we know root is the calling user. We use the system call * use the clockctl device before
*
* ntp_adjtime() is callable for mortals if tp->modes == 0 !
*/ */
if (__clockctl_fd == -1) { if (__clockctl_fd == -1) {
try_syscall:
q = __syscall((quad_t)SYS_ntp_adjtime, tp); q = __syscall((quad_t)SYS_ntp_adjtime, tp);
if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t) if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t)
|| /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN) || /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN)
@ -83,38 +84,23 @@ try_syscall:
rv = (int)((u_quad_t)q >> 32); rv = (int)((u_quad_t)q >> 32);
/* /*
* If credentials changed from root to an unprivilegied * if we fail with EPERM we try the clockctl device
* user, and we already had __clockctl_fd = -1, then we
* tried the system call as a non root user, it failed
* with EPERM, and we will try clockctl.
*/ */
if (rv != -1 || errno != EPERM) if (rv != -1 || errno != EPERM)
return rv; return rv;
__clockctl_fd = -2;
}
/*
* If __clockctl_fd = -2 then this is our first time here,
* or credentials have changed (the calling process dropped root
* root privilege). Check if root is the calling user. If it is,
* we try the system call, if it is not, we try clockctl.
*/
if (__clockctl_fd == -2) {
/*
* Root always uses the syscall
*/
if (geteuid() == 0) {
__clockctl_fd = -1;
goto try_syscall;
}
/* /*
* If this fails, it means that we are not root * If this fails, it means that we are not root
* and we cannot open clockctl. This is a failure. * and we cannot open clockctl. This is a true
* failure.
*/ */
__clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0); __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0);
if (__clockctl_fd == -1) if (__clockctl_fd == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1; return -1;
}
(void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC); (void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC);
} }
@ -133,6 +119,6 @@ try_syscall:
rv = (int)args.retval; rv = (int)args.retval;
return rv; return rv;
} }
return error;
return error;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: settimeofday.c,v 1.9 2006/08/17 09:59:55 jnemeth Exp $ */ /* $NetBSD: settimeofday.c,v 1.10 2006/10/07 20:02:01 kardel Exp $ */
/* /*
* Copyright (c) 2001 The NetBSD Foundation, Inc. * Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -33,7 +33,7 @@
#include <sys/cdefs.h> #include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint) #if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: settimeofday.c,v 1.9 2006/08/17 09:59:55 jnemeth Exp $"); __RCSID("$NetBSD: settimeofday.c,v 1.10 2006/10/07 20:02:01 kardel Exp $");
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include "namespace.h" #include "namespace.h"
@ -55,7 +55,7 @@ __RCSID("$NetBSD: settimeofday.c,v 1.9 2006/08/17 09:59:55 jnemeth Exp $");
__weak_alias(settimeofday,_settimeofday) __weak_alias(settimeofday,_settimeofday)
#endif #endif
int __clockctl_fd = -2; int __clockctl_fd = -1;
int int
settimeofday(tv, tzp) settimeofday(tv, tzp)
@ -63,16 +63,14 @@ settimeofday(tv, tzp)
const void *tzp; const void *tzp;
{ {
struct clockctl_settimeofday args; struct clockctl_settimeofday args;
int error;
quad_t q; quad_t q;
int rv; int rv;
/* /*
* if __clockctl_fd == -1, then this is not our first time, * try syscal first and attempt to switch to clockctl
* and we know root is the calling user. We use the system call * if that fails with EPERM
*/ */
if (__clockctl_fd == -1) { if (__clockctl_fd == -1) {
try_syscall:
q = __syscall((quad_t)SYS_settimeofday, tv, tzp); q = __syscall((quad_t)SYS_settimeofday, tv, tzp);
if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t) if (/* LINTED constant */ sizeof (quad_t) == sizeof (register_t)
|| /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN) || /* LINTED constant */ BYTE_ORDER == LITTLE_ENDIAN)
@ -81,41 +79,21 @@ try_syscall:
rv = (int)((u_quad_t)q >> 32); rv = (int)((u_quad_t)q >> 32);
/* /*
* If credentials changed from root to an unprivilegied * switch to clockctl if we fail with EPERM, this
* user, and we already had __clockctl_fd = -1, then we * may be cause by an attempt to set the time backwards
* tried the system call as a non root user, it failed * but we should leave the access permission checking
* with EPERM, and we will try clockctl unless the user * entirely to the kernel
* is root which means they probably tried to set the
* clock backwards and are not allowed to do so because
* of the securelevel.
*/ */
if (rv != -1 || errno != EPERM || geteuid() == 0) if (rv != -1 || errno != EPERM)
return rv; return rv;
__clockctl_fd = -2;
}
/* __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0);
* If __clockctl_fd = -2 then this is our first time here, if (__clockctl_fd == -1) {
* or credentials have changed (the calling process dropped root /* original error was EPERM - don't leak open errors */
* root privilege). Check if root is the calling user. If it is, errno = EPERM;
* we try the system call, if it is not, we try clockctl. return -1;
*/
if (__clockctl_fd == -2) {
/*
* Root always uses the syscall
*/
if (geteuid() == 0) {
__clockctl_fd = -1;
goto try_syscall;
} }
/*
* If this fails, it means that we are not root
* and we cannot open clockctl. This is a failure.
*/
__clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY, 0);
if (__clockctl_fd == -1)
return -1;
(void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC); (void) fcntl(__clockctl_fd, F_SETFD, FD_CLOEXEC);
} }
@ -125,6 +103,5 @@ try_syscall:
*/ */
args.tv = tv; args.tv = tv;
args.tzp = tzp; args.tzp = tzp;
error = ioctl(__clockctl_fd, CLOCKCTL_SETTIMEOFDAY, &args); return ioctl(__clockctl_fd, CLOCKCTL_SETTIMEOFDAY, &args);
return error;
} }