mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
Compare commits
10
Commits
039a8e11f8
...
d9d6e77965
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9d6e77965 | ||
|
|
eca7cba74c | ||
|
|
73b3fb41e6 | ||
|
|
8671e823b7 | ||
|
|
473cd1bba9 | ||
|
|
5bc997b6f5 | ||
|
|
e86a612d77 | ||
|
|
787e2e411d | ||
|
|
eb36c35ccf | ||
|
|
5760c22a05 |
No files matched your search
@@ -1428,7 +1428,7 @@ gsbase_load_fault:
|
||||
ALIGN_TEXT
|
||||
user_fred_syscall:
|
||||
movq %rdx,TF_RDX(%rsp)
|
||||
movq %rcx,TF_RCX(%rsp)
|
||||
movq %r11,TF_R11(%rsp)
|
||||
SAVE_SEGS
|
||||
movq PCPU(CURPCB),%r11
|
||||
andl $~PCB_FULL_IRET,PCB_FLAGS(%r11)
|
||||
@@ -1439,6 +1439,7 @@ user_fred_syscall:
|
||||
movq %r9,TF_R9(%rsp)
|
||||
movq %rbx,TF_RBX(%rsp)
|
||||
movq %rbp,TF_RBP(%rsp)
|
||||
movq %r10,TF_RCX(%rsp)
|
||||
movq %r12,TF_R12(%rsp)
|
||||
movq %r13,TF_R13(%rsp)
|
||||
movq %r14,TF_R14(%rsp)
|
||||
@@ -1462,10 +1463,11 @@ user_fred_syscall:
|
||||
movq TF_RSI(%rsp),%rsi
|
||||
movq TF_RDX(%rsp),%rdx
|
||||
movq TF_RAX(%rsp),%rax
|
||||
movq TF_RIP(%rsp),%rcx
|
||||
movq TF_RFLAGS(%rsp),%r11
|
||||
xorl %r8d,%r8d
|
||||
xorl %r9d,%r9d
|
||||
xorl %r10d,%r10d
|
||||
xorl %r11d,%r11d
|
||||
addq $TF_ERR,%rsp
|
||||
.globl fred_syscall_eretu
|
||||
fred_syscall_eretu:
|
||||
@@ -1648,10 +1650,10 @@ fred_events_handlers:
|
||||
movq %rsi,TF_RSI(%rsp)
|
||||
movl TF_FRED_EVINFO2(%rsp),%edi
|
||||
movl %edi,%eax
|
||||
andl $TF_FRED_EVINFO2_TYPEMASK,%edi
|
||||
cmpl $TF_FRED_EVINFO2_TYPE_SYSCALL,%edi
|
||||
je user_fred_syscall
|
||||
jmp user_fred_non_syscall
|
||||
andl $TF_FRED_EVINFO2_SYSCALLMASK,%edi
|
||||
cmpl $TF_FRED_EVINFO2_SYSCALLVAL,%edi
|
||||
jne user_fred_non_syscall
|
||||
jmp user_fred_syscall
|
||||
|
||||
. = fred_events_handlers + 256
|
||||
subq $TF_ERR,%rsp
|
||||
|
||||
@@ -190,9 +190,15 @@ ASSYM(TF_FRED_EVINFO2, offsetof(struct trapframe, tf_fred_evinfo2));
|
||||
ASSYM(TF_FLAGS, offsetof(struct trapframe, tf_flags));
|
||||
ASSYM(TF_SIZE, sizeof(struct trapframe));
|
||||
ASSYM(TF_HASSEGS, TF_HASSEGS);
|
||||
ASSYM(TF_FRED_EVINFO2_VECMASK, TF_FRED_EVINFO2_VECMASK);
|
||||
ASSYM(TF_FRED_EVINFO2_VEC_SYSCALL, TF_FRED_EVINFO2_VEC_SYSCALL);
|
||||
ASSYM(TF_FRED_EVINFO2_SYSCALLMASK, TF_FRED_EVINFO2_TYPEMASK |
|
||||
TF_FRED_EVINFO2_VECMASK | TF_FRED_EVINFO2_LM);
|
||||
ASSYM(TF_FRED_EVINFO2_TYPE_EXC, TF_FRED_EVINFO2_TYPE_EXC);
|
||||
ASSYM(TF_FRED_EVINFO2_TYPE_SYSCALL, TF_FRED_EVINFO2_TYPE_SYSCALL);
|
||||
ASSYM(TF_FRED_EVINFO2_TYPEMASK, TF_FRED_EVINFO2_TYPEMASK);
|
||||
ASSYM(TF_FRED_EVINFO2_SYSCALLVAL, TF_FRED_EVINFO2_TYPE_SYSCALL |
|
||||
TF_FRED_EVINFO2_VEC_SYSCALL | TF_FRED_EVINFO2_LM);
|
||||
ASSYM(TF_FRED_EVINFO2_INSTLENMASK, TF_FRED_EVINFO2_INSTLENMASK);
|
||||
ASSYM(TF_FRED_EVINFO2_INSTLENSHIFT, TF_FRED_EVINFO2_INSTLENSHIFT);
|
||||
|
||||
|
||||
@@ -451,14 +451,14 @@ amd64_cpu_init_fred(void)
|
||||
/*
|
||||
* With FRED, there is no need for workarounds requiring
|
||||
* dedicated stack for #DB. Also, there is no need to have
|
||||
* separate stacks for #NM and #MC, because CSL rules ensure
|
||||
* separate stacks for NMI and #MC, because CSL rules ensure
|
||||
* that interrupted frame is safe even if NMI was interrupted
|
||||
* by machine check or vice versa.
|
||||
*
|
||||
* Still, we need to provide a stack for events that can occur
|
||||
* with the interrupts disabled, to avoid caring about the
|
||||
* ordering of the context update in cpu_switch.S. Use CSL 1
|
||||
* for #NM and #MC.
|
||||
* for NMI and #MC.
|
||||
*
|
||||
* Since double fault handler is used to handle stack
|
||||
* overflow, it gets the dedicated stack, of the highest used
|
||||
@@ -467,7 +467,7 @@ amd64_cpu_init_fred(void)
|
||||
* CSL 3 is unused, and we have some space to re-arrange this
|
||||
* if a need in the future appears.
|
||||
*/
|
||||
wrmsr(MSR_FRED_STKLVLS, (1ul << (IDT_NM * 2)) |
|
||||
wrmsr(MSR_FRED_STKLVLS, (1ul << (IDT_NMI * 2)) |
|
||||
(1ul << (IDT_MC * 2)) | (2ul << (IDT_DF * 2)));
|
||||
wrmsr(MSR_FRED_RSP3, 0);
|
||||
load_cr4(rcr4() | CR4_FRED);
|
||||
|
||||
+12
-4
@@ -31,21 +31,29 @@
|
||||
|
||||
#include <machine/frame.h>
|
||||
#include <machine/iodev.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/psl.h>
|
||||
|
||||
int
|
||||
iodev_open(struct thread *td)
|
||||
{
|
||||
|
||||
td->td_frame->tf_rflags |= PSL_IOPL;
|
||||
/*
|
||||
* SDM rev. 93 vol.3 8.4.2.1 Loading and Checking the Return State:
|
||||
* Checking IOPL ensures that, when FRED transitions are
|
||||
* enabled, IOPL is always 0 when CPL = 3.
|
||||
*
|
||||
* As result, io(4) cannot enable the IOPL for usermode on FRED.
|
||||
*/
|
||||
if (!fred)
|
||||
td->td_frame->tf_rflags |= PSL_IOPL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
iodev_close(struct thread *td)
|
||||
{
|
||||
|
||||
td->td_frame->tf_rflags &= ~PSL_IOPL;
|
||||
if (!fred)
|
||||
td->td_frame->tf_rflags &= ~PSL_IOPL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
+27
-7
@@ -1573,6 +1573,24 @@ fred_inst_len(const struct trapframe_fred *frame)
|
||||
TF_FRED_EVINFO2_INSTLENSHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reaction to userspace having no permissions to generate the event.
|
||||
* Report T_PROTFLT and rewind %rip back to emulate fault instead of
|
||||
* trap.
|
||||
*/
|
||||
static void
|
||||
trap_fred_u_noperm(struct trapframe_fred *frame, ksiginfo_t *ksi)
|
||||
{
|
||||
frame->tf_idt.tf_rip -= fred_inst_len(frame);
|
||||
frame->tf_idt.tf_addr = 0;
|
||||
frame->tf_idt.tf_trapno = T_PROTFLT;
|
||||
ksiginfo_init_trap(ksi);
|
||||
ksi->ksi_signo = SIGBUS;
|
||||
ksi->ksi_code = BUS_OBJERR;
|
||||
ksi->ksi_trapno = T_PROTFLT;
|
||||
ksi->ksi_addr = (void *)frame->tf_idt.tf_rip;
|
||||
}
|
||||
|
||||
int fred_verbose_events;
|
||||
|
||||
void trap_fred_u(struct trapframe_fred *frame);
|
||||
@@ -1648,12 +1666,9 @@ trap_fred_u(struct trapframe_fred *frame)
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
frame->tf_idt.tf_trapno = vec;
|
||||
ksiginfo_init_trap(&ksi);
|
||||
ksi.ksi_signo = SIGBUS;
|
||||
ksi.ksi_code = BUS_OBJERR;
|
||||
ksi.ksi_trapno = frame->tf_idt.tf_trapno;
|
||||
ksi.ksi_addr = (void *)frame->tf_idt.tf_rip;
|
||||
trap_fred_u_noperm(frame, &ksi);
|
||||
/* error code: gate selector from IDT */
|
||||
frame->tf_idt.tf_err = (vec * 8) | 2;
|
||||
do_trapsig = true;
|
||||
break;
|
||||
case TF_FRED_EVINFO2_TYPE_SYSCALL:
|
||||
@@ -1665,7 +1680,8 @@ trap_fred_u(struct trapframe_fred *frame)
|
||||
amd64_syscall(td, (frame->tf_idt.tf_rflags & PSL_T) !=
|
||||
0);
|
||||
} else {
|
||||
/* SYSENTER returns without action */
|
||||
trap_fred_u_noperm(frame, &ksi);
|
||||
do_trapsig = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1815,6 +1831,10 @@ trap_fred_handle_k_exc(struct thread *td, struct trapframe_fred *frame,
|
||||
case IDT_MF:
|
||||
break;
|
||||
case IDT_AC:
|
||||
if (curpcb->pcb_onfault != NULL) {
|
||||
frame->tf_idt.tf_rip = (long)curpcb->pcb_onfault;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case IDT_MC:
|
||||
mca_intr();
|
||||
|
||||
@@ -88,6 +88,9 @@ linux_iopl(struct thread *td, struct linux_iopl_args *args)
|
||||
return (error);
|
||||
if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
|
||||
return (error);
|
||||
/* See comment in sys/amd64/amd64/io.c. */
|
||||
if (fred && args->level != 0)
|
||||
return (ENOSYS);
|
||||
td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
|
||||
(args->level * (PSL_IOPL / 3));
|
||||
|
||||
|
||||
@@ -332,6 +332,9 @@ linux_iopl(struct thread *td, struct linux_iopl_args *args)
|
||||
return (error);
|
||||
if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
|
||||
return (error);
|
||||
/* See comment in sys/amd64/amd64/io.c. */
|
||||
if (fred && args->level != 0)
|
||||
return (ENOSYS);
|
||||
td->td_frame->tf_rflags = (td->td_frame->tf_rflags & ~PSL_IOPL) |
|
||||
(args->level * (PSL_IOPL / 3));
|
||||
|
||||
|
||||
@@ -160,7 +160,14 @@ dsp_destroy_dev(device_t dev)
|
||||
struct snddev_info *d;
|
||||
|
||||
d = device_get_softc(dev);
|
||||
destroy_dev(d->dsp_dev);
|
||||
/*
|
||||
* The cdev may not exist if the driver failed before or during
|
||||
* pcm_register().
|
||||
*/
|
||||
if (d->dsp_dev != NULL) {
|
||||
destroy_dev(d->dsp_dev);
|
||||
d->dsp_dev = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -428,8 +428,6 @@ pcm_register(device_t dev, char *str)
|
||||
vchan_initsys(dev);
|
||||
feeder_eq_initsys(dev);
|
||||
|
||||
sndstat_register(dev, SNDST_TYPE_PCM, d->status);
|
||||
|
||||
err = dsp_make_dev(dev);
|
||||
if (err)
|
||||
return (err);
|
||||
@@ -441,6 +439,9 @@ pcm_register(device_t dev, char *str)
|
||||
}
|
||||
}
|
||||
|
||||
/* Publish only once registration really has finished properly. */
|
||||
sndstat_register(dev, SNDST_TYPE_PCM, d->status);
|
||||
|
||||
bus_topo_lock();
|
||||
if (snd_unit_auto < 0)
|
||||
snd_unit_auto = (snd_unit < 0) ? 1 : 0;
|
||||
@@ -463,8 +464,8 @@ pcm_unregister(device_t dev)
|
||||
|
||||
d = device_get_softc(dev);
|
||||
|
||||
if (!PCM_REGISTERED(d)) {
|
||||
device_printf(dev, "unregister: device not configured\n");
|
||||
if (!PCM_ALIVE(d)) {
|
||||
device_printf(dev, "unregister: device not initialized\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -496,6 +497,7 @@ pcm_unregister(device_t dev)
|
||||
|
||||
cv_destroy(&d->cv);
|
||||
mtx_destroy(&d->lock);
|
||||
d->dev = NULL;
|
||||
|
||||
bus_topo_lock();
|
||||
if (snd_unit == device_get_unit(dev)) {
|
||||
|
||||
@@ -122,8 +122,8 @@ struct snd_mixer;
|
||||
"\015PVCHANS" \
|
||||
"\016RVCHANS"
|
||||
|
||||
#define PCM_REGISTERED(x) \
|
||||
((x) != NULL && ((x)->flags & SD_F_REGISTERED))
|
||||
#define PCM_ALIVE(x) ((x) != NULL && (x)->dev != NULL)
|
||||
#define PCM_REGISTERED(x) (PCM_ALIVE(x) && ((x)->flags & SD_F_REGISTERED))
|
||||
|
||||
#define PCM_MAXCHANS 10000
|
||||
#define PCM_CHANCOUNT(d) \
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
#include <machine/psl.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/md_var.h>
|
||||
#endif
|
||||
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
@@ -1338,6 +1339,8 @@ sctty_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
|
||||
#ifdef __i386__
|
||||
td->td_frame->tf_eflags |= PSL_IOPL;
|
||||
#elif defined(__amd64__)
|
||||
if (fred)
|
||||
return (EINVAL);
|
||||
td->td_frame->tf_rflags |= PSL_IOPL;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/msan.h>
|
||||
#include <sys/sglist.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/bus.h>
|
||||
@@ -210,6 +211,7 @@ vt9p_intr_complete(void *xsc)
|
||||
struct vt9p_softc *chan;
|
||||
struct virtqueue *vq;
|
||||
struct p9_req_t *curreq;
|
||||
uint32_t len;
|
||||
|
||||
chan = (struct vt9p_softc *)xsc;
|
||||
vq = chan->vt9p_vq;
|
||||
@@ -218,8 +220,9 @@ vt9p_intr_complete(void *xsc)
|
||||
|
||||
VT9P_LOCK(chan);
|
||||
again:
|
||||
while ((curreq = virtqueue_dequeue(vq, NULL)) != NULL) {
|
||||
while ((curreq = virtqueue_dequeue(vq, &len)) != NULL) {
|
||||
curreq->rc.tag = curreq->tc.tag;
|
||||
kmsan_mark(curreq->rc.sdata, len, KMSAN_STATE_INITED);
|
||||
wakeup_one(curreq);
|
||||
}
|
||||
if (virtqueue_enable_intr(vq) != 0) {
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
#include <machine/psl.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/md_var.h>
|
||||
#endif
|
||||
|
||||
static int vtterm_cngrab_noswitch(struct vt_device *, struct vt_window *);
|
||||
@@ -2971,6 +2972,8 @@ skip_thunk:
|
||||
#if defined(__i386__)
|
||||
td->td_frame->tf_eflags |= PSL_IOPL;
|
||||
#elif defined(__amd64__)
|
||||
if (fred)
|
||||
return (EINVAL);
|
||||
td->td_frame->tf_rflags |= PSL_IOPL;
|
||||
#endif
|
||||
return (0);
|
||||
|
||||
@@ -54,11 +54,11 @@ class TestIGMP(VnetTestTemplate):
|
||||
packets = self.sp.sniff(iface=ifname, timeout=5)
|
||||
for r in packets:
|
||||
r.show()
|
||||
igmp = r.getlayer(self.sc.igmp.IGMP)
|
||||
igmp = r.getlayer(self.sl.igmp.IGMP)
|
||||
if not igmp:
|
||||
continue
|
||||
igmp.show()
|
||||
if not igmp.gaddr == "230.0.0.1":
|
||||
if getattr(igmp, 'gaddr', '0.0.0.0') != "230.0.0.1":
|
||||
continue
|
||||
found = True
|
||||
return found
|
||||
@@ -69,33 +69,32 @@ class TestIGMP(VnetTestTemplate):
|
||||
"""Verify that we allow IGMP packets with IP options"""
|
||||
ifname = self.vnet.iface_alias_map["if1"].name
|
||||
|
||||
# Import in the correct vnet, so at to not confuse Scapy
|
||||
# Import in the correct vnet, so as to not confuse Scapy
|
||||
import scapy.all as sp
|
||||
import scapy.contrib as sc
|
||||
import scapy.contrib.igmp
|
||||
import scapy.layers as sl
|
||||
self.sp = sp
|
||||
self.sc = sc
|
||||
self.sl = sl
|
||||
|
||||
# We allow IGMP packets with the router alert option
|
||||
pkt = sp.IP(dst="224.0.0.1%%%s" % ifname, ttl=1,
|
||||
options=[sp.IPOption_Router_Alert()]) \
|
||||
/ sc.igmp.IGMP(type=0x11, mrcode=1)
|
||||
/ sl.igmp.IGMP(type=0x11, mrcode=1)
|
||||
assert self.find_igmp_reply(pkt, ifname)
|
||||
|
||||
# But not with other options
|
||||
pkt = sp.IP(dst="224.0.0.1%%%s" % ifname, ttl=1,
|
||||
options=[sp.IPOption_NOP()]) \
|
||||
/ sc.igmp.IGMP(type=0x11, mrcode=1)
|
||||
/ sl.igmp.IGMP(type=0x11, mrcode=1)
|
||||
assert not self.find_igmp_reply(pkt, ifname)
|
||||
|
||||
# Or with the wrong TTL
|
||||
pkt = sp.IP(dst="224.0.0.1%%%s" % ifname, ttl=2,
|
||||
options=[sp.IPOption_Router_Alert()]) \
|
||||
/ sc.igmp.IGMP(type=0x11, mrcode=1)
|
||||
/ sl.igmp.IGMP(type=0x11, mrcode=1)
|
||||
assert not self.find_igmp_reply(pkt, ifname)
|
||||
|
||||
# Or with the wrong destination address
|
||||
pkt = sp.IP(dst="224.0.0.2%%%s" % ifname, ttl=2,
|
||||
options=[sp.IPOption_Router_Alert()]) \
|
||||
/ sc.igmp.IGMP(type=0x11, mrcode=1)
|
||||
/ sl.igmp.IGMP(type=0x11, mrcode=1)
|
||||
assert not self.find_igmp_reply(pkt, ifname)
|
||||
@@ -40,9 +40,7 @@ ATF_TC_BODY(mmap_offset_overflow, tc)
|
||||
buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, off);
|
||||
ATF_REQUIRE_MSG(buf == MAP_FAILED, FMT_ERR("mmap"));
|
||||
|
||||
munmap(buf, len);
|
||||
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -124,9 +122,7 @@ ATF_TC_BODY(mmap_reject_prot_exec, tc)
|
||||
fd, 0);
|
||||
ATF_REQUIRE_MSG(buf == MAP_FAILED, FMT_ERR("mmap"));
|
||||
|
||||
munmap(buf, len);
|
||||
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -98,7 +98,7 @@ ATF_TC_BODY(poll_kqueue, tc)
|
||||
ATF_REQUIRE_MSG(read(fd, buf, sizeof(buf)) > 0, FMT_ERR("read"));
|
||||
|
||||
EV_SET(&ev, fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
|
||||
close(kq);
|
||||
ATF_REQUIRE(close(kq) == 0);
|
||||
|
||||
kq = kqueue();
|
||||
ATF_REQUIRE_MSG(kq >= 0, FMT_ERR("kqueue"));
|
||||
@@ -113,9 +113,9 @@ ATF_TC_BODY(poll_kqueue, tc)
|
||||
ATF_REQUIRE_MSG(write(fd, buf, sizeof(buf)) > 0, FMT_ERR("write"));
|
||||
|
||||
EV_SET(&ev, fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
|
||||
close(kq);
|
||||
ATF_REQUIRE(close(kq) == 0);
|
||||
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
ATF_TC(poll_poll);
|
||||
@@ -154,7 +154,7 @@ ATF_TC_BODY(poll_poll, tc)
|
||||
wr = true;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
ATF_TC(poll_select);
|
||||
@@ -192,7 +192,7 @@ ATF_TC_BODY(poll_select, tc)
|
||||
wr = true;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
|
||||
@@ -196,7 +196,7 @@ ATF_TC_BODY(sndstat_nv, tc)
|
||||
|
||||
free(arg.buf);
|
||||
nvlist_destroy(nvl);
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
#define UDEV_PROVIDER "sndstat_udev"
|
||||
@@ -374,7 +374,7 @@ ATF_TC_BODY(sndstat_udev, tc)
|
||||
|
||||
free(arg.buf);
|
||||
nvlist_destroy(nvl);
|
||||
close(fd);
|
||||
ATF_REQUIRE(close(fd) == 0);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
|
||||
Reference in new issue
Block a user