Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157233441
D55039.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D55039.diff
View Options
diff --git a/lib/libsys/_libsys.h b/lib/libsys/_libsys.h
--- a/lib/libsys/_libsys.h
+++ b/lib/libsys/_libsys.h
@@ -475,6 +475,7 @@
typedef int (__sys_pdrfork_t)(int *, int, int);
typedef int (__sys_pdwait_t)(int, int *, int, struct __wrusage *, struct __siginfo *);
typedef int (__sys_renameat2_t)(int, const char *, int, const char *, int);
+typedef int (__sys_setrlimit_uid_t)(u_int, struct rlimit *, uid_t);
_Noreturn void __sys__exit(int rval);
int __sys_fork(void);
@@ -885,6 +886,7 @@
int __sys_pdrfork(int * fdp, int pdflags, int rfflags);
int __sys_pdwait(int fd, int * status, int options, struct __wrusage * wrusage, struct __siginfo * info);
int __sys_renameat2(int oldfd, const char * old, int newfd, const char * new, int flags);
+int __sys_setrlimit_uid(u_int which, struct rlimit * rlp, uid_t uid);
__END_DECLS
#endif /* __LIBSYS_H_ */
diff --git a/lib/libsys/getrlimit.2 b/lib/libsys/getrlimit.2
--- a/lib/libsys/getrlimit.2
+++ b/lib/libsys/getrlimit.2
@@ -30,7 +30,8 @@
.Os
.Sh NAME
.Nm getrlimit ,
-.Nm setrlimit
+.Nm setrlimit ,
+.Nm setrlimit_uid
.Nd control maximum system resource consumption
.Sh LIBRARY
.Lb libc
@@ -42,6 +43,7 @@
.Fn getrlimit "int resource" "struct rlimit *rlp"
.Ft int
.Fn setrlimit "int resource" "const struct rlimit *rlp"
+.Fn setrlimit_uid "int resource" "const struct rlimit *rlp" "uid_t uid"
.Sh DESCRIPTION
Limits on the consumption of system resources by the current process
and each process it creates may be obtained with the
@@ -50,6 +52,13 @@
.Fn setrlimit
system call.
.Pp
+Limits on the consumption of system resources for a specific UID
+and each process it creates may be obtained with the
+.Fn getrlimit
+system call, and set with the
+.Fn setrlimit_uid
+system call.
+.Pp
The
.Fa resource
argument is one of the following:
@@ -169,6 +178,20 @@
.Ic limit
is thus a built-in command to
.Xr csh 1 .
+This does not apply to the limits which are tracked globally for each user.
+These per-UID limits are:
+.Bl -dash -compact
+.It
+RLIMIT_KQUEUES
+.It
+RLIMIT_NPROC
+.It
+RLIMIT_NPTS
+.It
+RLIMIT_UMTXP
+.It
+RLIMIT_VMM
+.El
.Pp
The system refuses to extend the data or stack space when the limits
would be exceeded in the normal way: a
@@ -226,6 +249,17 @@
.Fn setrlimit
would have
raised the maximum limit value, and the caller is not the super-user.
+.It Bq Er EPERM
+The caller attempted to change a per-UID limit using
+.Fn setrlimit_uid
+and was not the super-user.
+.It Bq Er ENOENT
+The caller attempted to change a per-UID limit using
+.Fn setrlimit_uid
+and there are no active sessions for the request UID.
+.It Bq Er EINVAL
+The caller attempted to change a per-process limit using
+.Fn setrlimit_uid .
.El
.Sh SEE ALSO
.Xr csh 1 ,
@@ -242,8 +276,15 @@
.Fn setrlimit
functions are expected to conform to
.St -p1003.1-2001 .
+Per-UID limits and the
+.Fn setrlimit_uid
+function are non-standard.
.Sh HISTORY
The
.Fn getrlimit
system call appeared in
.Bx 4.2 .
+The
+.Fn setrlimit_uid
+system call appeared in
+.Fx 16.0 .
diff --git a/lib/libsys/syscalls.map b/lib/libsys/syscalls.map
--- a/lib/libsys/syscalls.map
+++ b/lib/libsys/syscalls.map
@@ -825,4 +825,6 @@
__sys_pdwait;
_renameat2;
__sys_renameat2;
+ _setrlimit_uid;
+ __sys_setrlimit_uid;
};
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -665,6 +665,7 @@
#define AUE_SETCRED 43271 /* FreeBSD-specific. */
#define AUE_INOTIFY 43272 /* FreeBSD/Linux. */
#define AUE_PDRFORK 43273 /* FreeBSD-specific. */
+#define AUE_SETRLIMIT_UID 43274 /* FreeBSD-specific. */
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -520,4 +520,5 @@
#define FREEBSD32_SYS_pdrfork 600
#define FREEBSD32_SYS_freebsd32_pdwait 601
#define FREEBSD32_SYS_renameat2 602
-#define FREEBSD32_SYS_MAXSYSCALL 603
+#define FREEBSD32_SYS_setrlimit_uid 603
+#define FREEBSD32_SYS_MAXSYSCALL 604
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -608,4 +608,5 @@
"pdrfork", /* 600 = pdrfork */
"freebsd32_pdwait", /* 601 = freebsd32_pdwait */
"renameat2", /* 602 = renameat2 */
+ "setrlimit_uid", /* 603 = setrlimit_uid */
};
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -670,4 +670,5 @@
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(freebsd32_pdwait_args), .sy_call = (sy_call_t *)freebsd32_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = freebsd32_pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
+ { .sy_narg = AS(setrlimit_uid_args), .sy_call = (sy_call_t *)sys_setrlimit_uid, .sy_auevent = AUE_SETRLIMIT_UID, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = setrlimit_uid */
};
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -3458,6 +3458,15 @@
*n_args = 5;
break;
}
+ /* setrlimit_uid */
+ case 603: {
+ struct setrlimit_uid_args *p = params;
+ uarg[a++] = p->which; /* u_int */
+ uarg[a++] = (intptr_t)p->rlp; /* struct rlimit * */
+ uarg[a++] = p->uid; /* uid_t */
+ *n_args = 3;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9347,6 +9356,22 @@
break;
};
break;
+ /* setrlimit_uid */
+ case 603:
+ switch (ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "userland struct rlimit *";
+ break;
+ case 2:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11280,6 +11305,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* setrlimit_uid */
+ case 603:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c
--- a/sys/kern/init_sysent.c
+++ b/sys/kern/init_sysent.c
@@ -669,4 +669,5 @@
{ .sy_narg = AS(pdrfork_args), .sy_call = (sy_call_t *)sys_pdrfork, .sy_auevent = AUE_PDRFORK, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 600 = pdrfork */
{ .sy_narg = AS(pdwait_args), .sy_call = (sy_call_t *)sys_pdwait, .sy_auevent = AUE_PDWAIT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 601 = pdwait */
{ .sy_narg = AS(renameat2_args), .sy_call = (sy_call_t *)sys_renameat2, .sy_auevent = AUE_RENAMEAT, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 602 = renameat2 */
+ { .sy_narg = AS(setrlimit_uid_args), .sy_call = (sy_call_t *)sys_setrlimit_uid, .sy_auevent = AUE_SETRLIMIT_UID, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 603 = setrlimit_uid */
};
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -55,6 +55,7 @@
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/time.h>
+#include <sys/types.h>
#include <sys/umtxvar.h>
#include <vm/vm.h>
@@ -654,7 +655,7 @@
case RLIMIT_NPTS:
case RLIMIT_PIPEBUF:
case RLIMIT_UMTXP:
- case RLIMIT_VMM:
+ case RLIMIT_VMS:
return true;
default:
return false;
@@ -940,6 +941,66 @@
error = copyout(&res, uap->res, sizeof(res));
return (error);
}
+#ifndef _SYS_SYSPROTO_H_
+struct setrlimit_uid_args {
+ u_int which;
+ struct rlimit *rlp;
+ uid_t uid;
+};
+#endif
+int
+sys_setrlimit_uid(struct thread *td, struct setrlimit_uid_args *uap)
+{
+ struct rlimit alim;
+ int error;
+
+ if ((error = copyin(uap->rlp, &alim, sizeof(struct rlimit))))
+ return (error);
+ return (kern_setrlimit_uid(td, uap->which, &alim, uap->uid));
+}
+
+int
+kern_setrlimit_uid(struct thread *td, u_int which, struct rlimit *limp, uid_t uid)
+{
+ struct rlimit *alimp;
+ struct uidinfo *ui;
+ int error;
+
+ if (which >= RLIM_NLIMITS || !rlim_is_per_uid(which))
+ return (EINVAL);
+
+ /* Preserve 'setrlimit' bugs. */
+ if (limp->rlim_cur < 0)
+ limp->rlim_cur = RLIM_INFINITY;
+ if (limp->rlim_max < 0)
+ limp->rlim_max = RLIM_INFINITY;
+
+ ui = uifind(uid);
+ if (ui == NULL)
+ return (ENOENT);
+
+ /*
+ * Allow a calling process owned by 'uid' to lower the per-UID limit.
+ */
+ if (td->td_ucred->cr_uid != uid &&
+ (error = priv_check(td, PRIV_PROC_SETRLIMIT_UID)))
+ return (error);
+
+ mtx_lock(&ui->ui_limlock);
+ alimp = &ui->ui_limit->pl_rlimit[which];
+ if (limp->rlim_cur > alimp->rlim_max ||
+ limp->rlim_max > alimp->rlim_max)
+ if ((error = priv_check(td, PRIV_PROC_SETRLIMIT_UID))) {
+ mtx_unlock(&ui->ui_limlock);
+ return (error);
+ }
+ if (limp->rlim_cur > limp->rlim_max)
+ limp->rlim_cur = limp->rlim_max;
+ *alimp = *limp;
+ mtx_unlock(&ui->ui_limlock);
+
+ return (0);
+}
/*
* Transform the running time and tick information for children of proc p
diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c
--- a/sys/kern/syscalls.c
+++ b/sys/kern/syscalls.c
@@ -608,4 +608,5 @@
"pdrfork", /* 600 = pdrfork */
"pdwait", /* 601 = pdwait */
"renameat2", /* 602 = renameat2 */
+ "setrlimit_uid", /* 603 = setrlimit_uid */
};
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -3429,4 +3429,11 @@
int flags
);
}
+603 AUE_SETRLIMIT_UID STD|CAPENABLED {
+ int setrlimit_uid(
+ u_int which,
+ _In_ struct rlimit *rlp,
+ uid_t uid
+ );
+ }
; vim: syntax=off
diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c
--- a/sys/kern/systrace_args.c
+++ b/sys/kern/systrace_args.c
@@ -3555,6 +3555,15 @@
*n_args = 5;
break;
}
+ /* setrlimit_uid */
+ case 603: {
+ struct setrlimit_uid_args *p = params;
+ uarg[a++] = p->which; /* u_int */
+ uarg[a++] = (intptr_t)p->rlp; /* struct rlimit * */
+ uarg[a++] = p->uid; /* uid_t */
+ *n_args = 3;
+ break;
+ }
default:
*n_args = 0;
break;
@@ -9521,6 +9530,22 @@
break;
};
break;
+ /* setrlimit_uid */
+ case 603:
+ switch (ndx) {
+ case 0:
+ p = "u_int";
+ break;
+ case 1:
+ p = "userland struct rlimit *";
+ break;
+ case 2:
+ p = "uid_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
@@ -11549,6 +11574,11 @@
if (ndx == 0 || ndx == 1)
p = "int";
break;
+ /* setrlimit_uid */
+ case 603:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
diff --git a/sys/sys/param.h b/sys/sys/param.h
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -110,6 +110,7 @@
#define P_OSREL_TLSBASE 1500044
#define P_OSREL_EXTERRCTL 1500045
#define P_OSREL_AMD64_TF_FRED 1600014
+#define P_OSREL_SETRLIMIT_UID 1600018
#define P_OSREL_MAJOR(x) ((x) / 100000)
#endif
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -162,6 +162,7 @@
#define PRIV_PROC_SETLOGIN 161 /* Can call setlogin. */
#define PRIV_PROC_SETRLIMIT 162 /* Can raise resources limits. */
#define PRIV_PROC_SETLOGINCLASS 163 /* Can call setloginclass(2). */
+#define PRIV_PROC_SETRLIMIT_UID 164 /* Can call setrlimit_uid(2). */
/*
* System V IPC privileges.
diff --git a/sys/sys/resource.h b/sys/sys/resource.h
--- a/sys/sys/resource.h
+++ b/sys/sys/resource.h
@@ -41,6 +41,11 @@
#define _ID_T_DECLARED
#endif
+#ifndef _UID_T_DECLARED
+typedef __uid_t uid_t;
+#define _UID_T_DECLARED
+#endif
+
#ifndef _RLIM_T_DECLARED
typedef __rlim_t rlim_t;
#define _RLIM_T_DECLARED
@@ -192,6 +197,7 @@
int getrusage(int, struct rusage *);
int setpriority(int, int, int);
int setrlimit(int, const struct rlimit *);
+int setrlimit_uid(int, const struct rlimit *, uid_t);
#if __BSD_VISIBLE
int getrlimitusage(unsigned which, int flags, rlim_t *res);
#endif
diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h
--- a/sys/sys/syscall.h
+++ b/sys/sys/syscall.h
@@ -541,4 +541,5 @@
#define SYS_pdrfork 600
#define SYS_pdwait 601
#define SYS_renameat2 602
-#define SYS_MAXSYSCALL 603
+#define SYS_setrlimit_uid 603
+#define SYS_MAXSYSCALL 604
diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk
--- a/sys/sys/syscall.mk
+++ b/sys/sys/syscall.mk
@@ -444,4 +444,5 @@
kexec_load.o \
pdrfork.o \
pdwait.o \
- renameat2.o
+ renameat2.o \
+ setrlimit_uid.o
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -331,6 +331,7 @@
struct itimerval *);
int kern_setpriority(struct thread *td, int which, int who, int prio);
int kern_setrlimit(struct thread *, u_int, struct rlimit *);
+int kern_setrlimit_uid(struct thread *, u_int, struct rlimit *, uid_t);
int kern_setsockopt(struct thread *td, int s, int level, int name,
const void *optval, enum uio_seg valseg, socklen_t valsize);
int kern_settimeofday(struct thread *td, struct timeval *tv,
diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h
--- a/sys/sys/sysproto.h
+++ b/sys/sys/sysproto.h
@@ -1932,6 +1932,11 @@
char new_l_[PADL_(const char *)]; const char * new; char new_r_[PADR_(const char *)];
char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)];
};
+struct setrlimit_uid_args {
+ char which_l_[PADL_(u_int)]; u_int which; char which_r_[PADR_(u_int)];
+ char rlp_l_[PADL_(struct rlimit *)]; struct rlimit * rlp; char rlp_r_[PADR_(struct rlimit *)];
+ char uid_l_[PADL_(uid_t)]; uid_t uid; char uid_r_[PADR_(uid_t)];
+};
int sys__exit(struct thread *, struct _exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_read(struct thread *, struct read_args *);
@@ -2342,6 +2347,7 @@
int sys_pdrfork(struct thread *, struct pdrfork_args *);
int sys_pdwait(struct thread *, struct pdwait_args *);
int sys_renameat2(struct thread *, struct renameat2_args *);
+int sys_setrlimit_uid(struct thread *, struct setrlimit_uid_args *);
#ifdef COMPAT_43
@@ -3344,6 +3350,7 @@
#define SYS_AUE_pdrfork AUE_PDRFORK
#define SYS_AUE_pdwait AUE_PDWAIT
#define SYS_AUE_renameat2 AUE_RENAMEAT
+#define SYS_AUE_setrlimit_uid AUE_SETRLIMIT_UID
#undef PAD_
#undef PADL_
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, May 20, 1:29 PM (6 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33348561
Default Alt Text
D55039.diff (14 KB)
Attached To
Mode
D55039: Introduce setrlimit_uid(2)
Attached
Detach File
Event Timeline
Log In to Comment