RE: how to tell if a process is 64-bit
Hi, > In a cross-platform process utility tool the question came up how to decide if a process is 64-bit. > > https://github.com/giampaolo/psutil/issues/1102 > > What's the best answer for NetBSD? If I understand correctly, you want psutil-based scripts -- which seem to be written in Python -- to be able to ask "is-64" about other processes? I suppose you are therefore interested in knowing the base ISA of a given process from outside the process? (As others have mentioned, you might instead, or additionally, be interested in the emulation that's in use.) Are you looking for the system calls, or the python equivalents? Can you clarify? Best regards, --Terry
re: how to tell if a process is 64-bit
> > In addition to amd64/i386, it occurs to me that sparc64/sparc32 is > > another case; IIRC it's possible to take sparc64 hardware and build a > > (special? not sure) kernel that runs sparc32 userland. I've never > > tried it; I don't know whether sparc32 and sparc64 are as freely > > mixable at runtime as amd64 and i386 are under amd64 kernels. > > Yes, that's what compat/netbsd32 is for. (Of course, there are still a > few things like mount I never bothered to get working across ABIs.) there are a few supported cases here: 32 bit kernel on 64 bit cpu (32 bit userland only). 64 bit kernel with either size userland. eeh - matt@ fixed mount compat a few years ago, as well as a lot of the remaining edge cases we'd never gotten to. it was necessary to run full n32 userland on n64 kernel (we still build all the kvm-on-running-kernel-using programs as n64.) so that generally works fine now.. .mrg.
Re: how to tell if a process is 64-bit
> That's why I asked "what does 'is 64-bit' mean". Your previous reference to$ Any particular reason for the paragraph-length line? Manually repairing it (and trimming to the part I'm replying to), > [...] the question "does this program use 64 bit addresses". There > are at least two other possible questions: (a) does this program have > access to 64 bit registers, and (b) can this program do operations > such as arithmetic on 64 bit integers. You would be hard-pressed to find a platform on which (b) is false (and I'm not restricting that to NetBSD-supporting platforms, though I think I would have to restrict it to devices that were designed to be general-purpose computers). Even things like the tiny little MC68HC908QY4 8-bit microcontrollers in 16-pin DIP packages I've currently lost my tube of can do 64-bit arithmetic. Not fast (they don't do _anything_ fast), and not in single instructions, but so what? Even a sparc64 machine can't do a general-purpose 64-bit add in a single instruction unless both inputs are already in registers and leaving the output in a register is acceptable. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: how to tell if a process is 64-bit
On Fri, 8 Sep 2017, Mouse wrote: > >> ([...] on most "64-bit" ports, a real question on amd64 (and others, > >> if any) which support 32-bit userland.) > > actually -- our mips64 ports largely use N32 userland, which is 64 > > bit registers and 32 bit addresses. > > Oh! Thank you. Yes, that's an interesting case. > > In addition to amd64/i386, it occurs to me that sparc64/sparc32 is > another case; IIRC it's possible to take sparc64 hardware and build a > (special? not sure) kernel that runs sparc32 userland. I've never > tried it; I don't know whether sparc32 and sparc64 are as freely > mixable at runtime as amd64 and i386 are under amd64 kernels. Yes, that's what compat/netbsd32 is for. (Of course, there are still a few things like mount I never bothered to get working across ABIs.) Eduardo
Re: how to tell if a process is 64-bit
>> ([...] on most "64-bit" ports, a real question on amd64 (and others, >> if any) which support 32-bit userland.) > actually -- our mips64 ports largely use N32 userland, which is 64 > bit registers and 32 bit addresses. Oh! Thank you. Yes, that's an interesting case. In addition to amd64/i386, it occurs to me that sparc64/sparc32 is another case; IIRC it's possible to take sparc64 hardware and build a (special? not sure) kernel that runs sparc32 userland. I've never tried it; I don't know whether sparc32 and sparc64 are as freely mixable at runtime as amd64 and i386 are under amd64 kernels. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: how to tell if a process is 64-bit
> On Sep 8, 2017, at 4:00 PM, matthew greenwrote: > >> Is the answer "it's using an ISA with 64-bit registers and addresses"? >> This actually can be broken down into the "registers" and "addresses" >> portion, but, in practice, the two tend to go together. (Always true >> on most "64-bit" ports, a real question on amd64 (and others, if any) >> which support 32-bit userland.) > > actually -- our mips64 ports largely use N32 userland, which > is 64 bit registers and 32 bit addresses. this is also what > linux calls "x32" for x86 platforms. obviously, this does > require a 64 bit cpu. That's why I asked "what does 'is 64-bit' mean". Your previous reference to LP64 answers the question "does this program use 64 bit addresses". There are at least two other possible questions: (a) does this program have access to 64 bit registers, and (b) can this program do operations such as arithmetic on 64 bit integers. (a) presumably implies (b) but the two are not equivalent. For example, N32 is (a) and (b) but O32 -- the old "mips32" port -- is (b) but not (a). paul
re: how to tell if a process is 64-bit
> Is the answer "it's using an ISA with 64-bit registers and addresses"? > This actually can be broken down into the "registers" and "addresses" > portion, but, in practice, the two tend to go together. (Always true > on most "64-bit" ports, a real question on amd64 (and others, if any) > which support 32-bit userland.) actually -- our mips64 ports largely use N32 userland, which is 64 bit registers and 32 bit addresses. this is also what linux calls "x32" for x86 platforms. obviously, this does require a 64 bit cpu. .mrg.
re: how to tell if a process is 64-bit
> In a cross-platform process utility tool the question came up how to > decide if a process is 64-bit. > > https://github.com/giampaolo/psutil/issues/1102 > > What's the best answer for NetBSD? in C: internally, just check #ifdef _LP64. externally, kvm_getprocs() with KERN_PROC_PID. in other languages? don't ask me. .mrg.
Re: fork1 use-after-free of the child process
On 08.09.2017 04:32, Mateusz Guzik wrote: > The fork1 routine can wait for the child to exit (if vforked) and/or > return the pointer to the child. > > Neither case guarantees the safety of said operation. The key is that > the parent can be ignoring SIGCHLD, which results in autoreaping the > child and the child itself is made runnable. Thus in particular it can > exit and get its struct proc freed. No prevention measures are taken > AFAICS. > > I did not test it on the NetBSD kernel, but it's a standard problem and > the code definitely looks buggy. > > 1. returning the pointer > > The last parameter to fork1 is struct proc **rnewprocp. I found only 2 > uses: > - linux_sys_clone - the parameter is populated from a local variable > which is not used afterwards, i.e. the func can as well start passing > NULL instead > - creation of initproc - since this becomes the only remaining use of > the parameter I think it makes sense to get rid of it altogether. the > simplest hack which comes to mind will simply proc_find_raw the > process after fork return > > 2. vfork > > By the end there is: > while (p2->p_lflag & PL_PPWAIT) > cv_wait(>p_waitcv, proc_lock); > > Retesting after wake up triggers the bug. > > The cleanest solution I'm aware of introduces a dedicated condvar to use > by vfork. The parent uses a local variable for this purpose. Since the > condvar is only used by vfork to signal exec/exit, there is no need > to access the child after waking up. The downside is extention of struct > proc with a pointer. Interestingly this is what they do in Linux. > > FreeBSD does the obvious of grabbing a reference preventing the > destruction of struct proc from going through. > > Solaris suprisingly has a total hack: they look up the pid and see if > found process (if any) has to be waited on. Apart from general ugliness > it's also a minor scalability problem due to extra lock/unlock of the > global process list lock. > > -- > Mateusz Guzik http://gmail.com>> Thank you for the analysis. There is also a correctness problem with ptrace(2). I had trouble to generate the PTRACE_VFORK event. The first one for the parent that calls vfork(2) and reports child's PID; the second one that is generated by vforkee and returns forker's PID. When the child calls exec(2)/exit(2) and parent is resuming, there shall be reported PTRACE_VFORK_DONE once with PID of vforkee. Another topic is that we always want to get PTRACE_FORK and PTRACE_VFORK generated by the parent first and followed by a signal from the child. This deterministic order simplifies a debugger. Once I will sort out bugs with threads (LWPs) under a tracer, I will be back to this topic. signature.asc Description: OpenPGP digital signature
unsafe ->p_cwdi access in mount_checkdirs
In mount_checkdirs you can find a loop: mutex_enter(proc_lock); PROCLIST_FOREACH(p, ) { if ((cwdi = p->p_cwdi) == NULL) continue; if (cwdi->cwdi_cdir != olddp && cwdi->cwdi_rdir != olddp) continue; retry = true; rele1 = NULL; rele2 = NULL; atomic_inc_uint(>cwdi_refcnt); mutex_exit(proc_lock); rw_enter(>cwdi_lock, RW_WRITER); The problem is that p_cwdi IS NOT protected by proc_lock. The exit path uses reflock to destroy the object. Since this function is not performance critical, my suggested fix is to uncondionally take the p_lock and ref cwdi only if the process is alive and constructed. Alternatively, cwdi freeing can be split into 2 parts where actual freeing of the cwdi object itself is postponed until after proc_lock lock/unlock dance. Pseudo-code: struct cwdinfo * cwddestroy(struct cwdinfo *cwdi) { if (atomic_dec_uint_nv(>cwdi_refcnt) > 0) return NULL; vrele(cwdi->cwdi_cdir); if (cwdi->cwdi_rdir) vrele(cwdi->cwdi_rdir); if (cwdi->cwdi_edir) vrele(cwdi->cwdi_edir); return cwdi; } void cwdfree(struct cwdinfo *cwdi) { pool_cache_put(cwdi_cache, cwdi); } Then the exit path would: cwdi = cwddestroy(p->p_cwdi); p->p_cwdi = NULL; mutex_enter(proc_lock); mutex_exit(proc_lock); cwdfree(cwdi); mount_checkdirs would then atomic_inc_not_zero (or however you have this named). With the above, if cwdi was spotted, it is guaranteeed to not get freed until after proc_lock is dropped. A successfull non-zero -> non-zero + 1 refcount bump guarantees it wont get freed and the content will remain valid. -- Mateusz Guzik
Re: how to tell if a process is 64-bit
On Fri, Sep 08, 2017 at 01:13:44PM +, Christos Zoulas wrote: > If you can attach to it with ktrace, the first record is an emul record. > If you have procfs cat /proc//emul Yeah, but it would be interesting to see in something like kprocinfo2 (easily fetchable via sysctl or the kvm wrapper). Martin
Re: how to tell if a process is 64-bit
In article <20170908115647.ga29...@mail.duskware.de>, Martin Husemannwrote: >On Fri, Sep 08, 2017 at 12:55:37PM +0200, Thomas Klausner wrote: >> What's the best answer for NetBSD? > >If the kernel is 64bit: >kvm_getproc2() and check the process flags for P_32. > >If not: all of them ;-} > >I would find it more interesting to answer "what is the emulation it runs >under", so you have, say: netbsd native x86_64 processes, netbsd_compat32 >i386 processes, 32 bit linux, 64 bit linux, (but I don't know an >easy answer for that). If you can attach to it with ktrace, the first record is an emul record. If you have procfs cat /proc//emul christos
Re: how to tell if a process is 64-bit
>> First, I have to ask: what does it mean to say that a particular >> process is - or isn't - 64-bit? > Many 64-bit ports support running 32-bit applications > (compat_netbsd32, compat_linux32). Exactly. Is the answer "it can do arithmetic on 64-bit values"? (Most - all, I think - NetBSD ports qualify. Indeed, I have trouble imagining any machine with pretensions to general-purpose use, even 8-bitters like the C=64, that doesn't.) Is the answer "the CPU has 64-bit internal datapaths"? (This is not a per-process thing; it is probably true of some CPUs usually thought of as 32-bit and probably false of some low-end "64-bit" CPUs.) Is the answer "it's using an ISA with 64-bit registers and addresses"? This actually can be broken down into the "registers" and "addresses" portion, but, in practice, the two tend to go together. (Always true on most "64-bit" ports, a real question on amd64 (and others, if any) which support 32-bit userland.) Is the answer "it can address more than 4G of VM"? (This is probably equivalent, in practice, to the previous one.) Is the answer "it can address VM above the 4G point"? (For some ways of looking at the questions, this is equiavlent to the previous one. I think amd64 CPUs can do this under some circumstances when executing their 32-bit ISA, though I'd have to check the architecture document to be sure, and they may be limited to something like the 64G point.) I suspect the original question was thinking of the middle one, probably with regard to amd64/i386. I _think_ the CPU in that case can switch its ISA on the fly; if so, the question may need to be more "is it a 64-bit process at some particular moment?". If not, "which emulation is it using?" may be close enough to be useful, and is easy to answer, though perhaps somewhat inconvenient (ktrace writes a record with the emulation type; with no tracing points turned on that should be all it writes). /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Re: how to tell if a process is 64-bit
On Fri, Sep 08, 2017 at 07:38:24AM -0400, Mouse wrote: > First, I have to ask: what does it mean to say that a particular > process is - or isn't - 64-bit? Many 64-bit ports support running 32-bit applications (compat_netbsd32, compat_linux32). Thomas
Re: how to tell if a process is 64-bit
On Fri, Sep 08, 2017 at 12:55:37PM +0200, Thomas Klausner wrote: > What's the best answer for NetBSD? If the kernel is 64bit: kvm_getproc2() and check the process flags for P_32. If not: all of them ;-} I would find it more interesting to answer "what is the emulation it runs under", so you have, say: netbsd native x86_64 processes, netbsd_compat32 i386 processes, 32 bit linux, 64 bit linux, (but I don't know an easy answer for that). Martin
Re: how to tell if a process is 64-bit
At the risk of making people angry, this answer works for linux and netbsd: $ file -L /proc/self/exe /proc/self/exe: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /usr/libexec/ld.elf_so, for NetBSD 8.99.2, not stripped
Re: how to tell if a process is 64-bit
> In a cross-platform process utility tool the question came up how to > decide if a process is 64-bit. First, I have to ask: what does it mean to say that a particular process is - or isn't - 64-bit? I started to write that on most of the 64-bit-supporting ports there isn't even any question, but then I realized that, depending on the answer to the above, that may not be true. /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTMLmo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
how to tell if a process is 64-bit
Hi! In a cross-platform process utility tool the question came up how to decide if a process is 64-bit. https://github.com/giampaolo/psutil/issues/1102 What's the best answer for NetBSD? Thomas
fork1 use-after-free of the child process
The fork1 routine can wait for the child to exit (if vforked) and/or return the pointer to the child. Neither case guarantees the safety of said operation. The key is that the parent can be ignoring SIGCHLD, which results in autoreaping the child and the child itself is made runnable. Thus in particular it can exit and get its struct proc freed. No prevention measures are taken AFAICS. I did not test it on the NetBSD kernel, but it's a standard problem and the code definitely looks buggy. 1. returning the pointer The last parameter to fork1 is struct proc **rnewprocp. I found only 2 uses: - linux_sys_clone - the parameter is populated from a local variable which is not used afterwards, i.e. the func can as well start passing NULL instead - creation of initproc - since this becomes the only remaining use of the parameter I think it makes sense to get rid of it altogether. the simplest hack which comes to mind will simply proc_find_raw the process after fork return 2. vfork By the end there is: while (p2->p_lflag & PL_PPWAIT) cv_wait(>p_waitcv, proc_lock); Retesting after wake up triggers the bug. The cleanest solution I'm aware of introduces a dedicated condvar to use by vfork. The parent uses a local variable for this purpose. Since the condvar is only used by vfork to signal exec/exit, there is no need to access the child after waking up. The downside is extention of struct proc with a pointer. Interestingly this is what they do in Linux. FreeBSD does the obvious of grabbing a reference preventing the destruction of struct proc from going through. Solaris suprisingly has a total hack: they look up the pid and see if found process (if any) has to be waited on. Apart from general ugliness it's also a minor scalability problem due to extra lock/unlock of the global process list lock. -- Mateusz Guzik