syscalls: fix missing SIGSYS for several ENOSYS errors

In particular, when the syscall number is too large, or when syscall is
dynamic.  For that, add nosys_sysent structure to pass fake sysent to
syscall top code.

Reviewed by:	dchagin, markj
Discussed with:	jhb
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D41976
This commit is contained in:
Konstantin Belousov committed 2023-10-03 01:30:52 +03:00
1 parent 6b3bb233cd
commit 39024a8914
14 files changed
+35 -19

No files matched your search

+1 -1
View File
@@ -1033,7 +1033,7 @@ cpu_fetch_syscall_args_fallback(struct thread *td, struct syscall_args *sa)
}
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -183,7 +183,7 @@ ia32_fetch_syscall_args(struct thread *td)
params += sizeof(quad_t);
}
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -118,7 +118,7 @@ cpu_fetch_syscall_args(struct thread *td)
}
p = td->td_proc;
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
error = 0;
+1 -1
View File
@@ -191,7 +191,7 @@ freebsd32_fetch_syscall_args(struct thread *td)
}
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -151,7 +151,7 @@ cpu_fetch_syscall_args(struct thread *td)
}
if (__predict_false(sa->code >= p->p_sysent->sv_size))
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -123,7 +123,7 @@ linux_fetch_syscall_args(struct thread *td)
sa->original_code = sa->code;
/* LINUXTODO: generic syscall? */
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -1113,7 +1113,7 @@ cpu_fetch_syscall_args(struct thread *td)
}
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -522,7 +522,7 @@ linux_fetch_syscall_args(struct thread *td)
if (sa->code >= p->p_sysent->sv_size)
/* nosys */
sa->callp = &p->p_sysent->sv_table[p->p_sysent->sv_size - 1];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+2 -1
View File
@@ -2686,7 +2686,8 @@ ptrace_syscallreq(struct thread *td, struct proc *p,
audited = AUDIT_SYSCALL_ENTER(sc, td) != 0;
if (!sy_thr_static) {
error = syscall_thread_enter(td, se);
error = syscall_thread_enter(td, &se);
sy_thr_static = (se->sy_thrcnt & SY_THR_STATIC) != 0;
if (error != 0) {
tsr->ts_ret.sr_error = error;
return;
+19 -6
View File
@@ -61,6 +61,17 @@ lkmressys(struct thread *td, struct nosys_args *args)
return (nosys(td, args));
}
struct sysent nosys_sysent = {
.sy_call = (sy_call_t *)nosys,
.sy_systrace_args_func = NULL,
.sy_narg = 0,
.sy_flags = SYF_CAPENABLED,
.sy_auevent = AUE_NULL,
.sy_entry = 0, /* DTRACE_IDNONE */
.sy_return = 0,
.sy_thrcnt = SY_THR_STATIC,
};
static void
syscall_thread_drain(struct sysent *se)
{
@@ -78,19 +89,21 @@ syscall_thread_drain(struct sysent *se)
}
int
syscall_thread_enter(struct thread *td, struct sysent *se)
syscall_thread_enter(struct thread *td, struct sysent **se)
{
uint32_t cnt, oldcnt;
KASSERT((se->sy_thrcnt & SY_THR_STATIC) == 0,
KASSERT(((*se)->sy_thrcnt & SY_THR_STATIC) == 0,
("%s: not a static syscall", __func__));
do {
oldcnt = se->sy_thrcnt;
if ((oldcnt & (SY_THR_DRAINING | SY_THR_ABSENT)) != 0)
return (ENOSYS);
oldcnt = (*se)->sy_thrcnt;
if ((oldcnt & (SY_THR_DRAINING | SY_THR_ABSENT)) != 0) {
*se = &nosys_sysent;
return (0);
}
cnt = oldcnt + SY_THR_INCR;
} while (atomic_cmpset_acq_32(&se->sy_thrcnt, oldcnt, cnt) == 0);
} while (atomic_cmpset_acq_32(&(*se)->sy_thrcnt, oldcnt, cnt) == 0);
return (0);
}
+2 -1
View File
@@ -144,7 +144,8 @@ syscallenter(struct thread *td)
AUDIT_SYSCALL_ENTER(sa->code, td) ||
!sy_thr_static)) {
if (!sy_thr_static) {
error = syscall_thread_enter(td, se);
error = syscall_thread_enter(td, &se);
sy_thr_static = (se->sy_thrcnt & SY_THR_STATIC) != 0;
if (error != 0) {
td->td_errno = error;
goto retval;
+1 -1
View File
@@ -694,7 +694,7 @@ cpu_fetch_syscall_args(struct thread *td)
}
if (sa->code >= p->p_sysent->sv_size)
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+1 -1
View File
@@ -115,7 +115,7 @@ cpu_fetch_syscall_args(struct thread *td)
}
if (__predict_false(sa->code >= p->p_sysent->sv_size))
sa->callp = &p->p_sysent->sv_table[0];
sa->callp = &nosys_sysent;
else
sa->callp = &p->p_sysent->sv_table[sa->code];
+2 -1
View File
@@ -191,6 +191,7 @@ struct sysentvec {
extern struct sysentvec aout_sysvec;
extern struct sysent sysent[];
extern const char *syscallnames[];
extern struct sysent nosys_sysent;
struct nosys_args {
register_t dummy;
@@ -319,7 +320,7 @@ struct nosys_args;
int lkmnosys(struct thread *, struct nosys_args *);
int lkmressys(struct thread *, struct nosys_args *);
int syscall_thread_enter(struct thread *td, struct sysent *se);
int syscall_thread_enter(struct thread *td, struct sysent **se);
void syscall_thread_exit(struct thread *td, struct sysent *se);
int shared_page_alloc(int size, int align);