mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 04:43:53 +00:00
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:
parent
6b3bb233cd
commit
39024a8914
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue