From owner-freebsd-hackers@freebsd.org Tue Dec 18 05:58:38 2018 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 182B21341A3D for ; Tue, 18 Dec 2018 05:58:38 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from kib.kiev.ua (kib.kiev.ua [IPv6:2001:470:d5e7:1::1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id EBBD281503 for ; Tue, 18 Dec 2018 05:58:36 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from tom.home (kib@localhost [127.0.0.1]) by kib.kiev.ua (8.15.2/8.15.2) with ESMTPS id wBI5wSLI094735 (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 18 Dec 2018 07:58:32 +0200 (EET) (envelope-from kostikbel@gmail.com) DKIM-Filter: OpenDKIM Filter v2.10.3 kib.kiev.ua wBI5wSLI094735 Received: (from kostik@localhost) by tom.home (8.15.2/8.15.2/Submit) id wBI5wScs094734; Tue, 18 Dec 2018 07:58:28 +0200 (EET) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: tom.home: kostik set sender to kostikbel@gmail.com using -f Date: Tue, 18 Dec 2018 07:58:28 +0200 From: Konstantin Belousov To: Austin Shafer Cc: freebsd-hackers@freebsd.org Subject: Re: ENOMEM when calling sysctl_handle_int from custom handler Message-ID: <20181218055828.GA60291@kib.kiev.ua> References: <861s6fpyua.fsf@triplebuff.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <861s6fpyua.fsf@triplebuff.com> User-Agent: Mutt/1.11.1 (2018-12-01) X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,BAYES_00, DKIM_ADSP_CUSTOM_MED,FORGED_GMAIL_RCVD,FREEMAIL_FROM, NML_ADSP_CUSTOM_MED autolearn=no autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on tom.home X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Dec 2018 05:58:38 -0000 On Mon, Dec 17, 2018 at 05:34:05PM -0500, Austin Shafer wrote: > Hi freebsd-hackers, > > I've had an issue with creating a custom sysctl handler that I can't > seem to find an answer for. Using sysctl_handle_int as a handler in > SYSCTL_ADD_PROC works fine, but calling sysctl_handle_int from a custom > sysctl handler results in an error. > > (sorry for the long message, I tried to be verbose) > > Creating the nodes works fine, but SYSCTL_OUT or sysctl_handle_int > return ENOMEM despite there being plenty of available memory. I based my > approach on other areas of the source where those sysctls work without > error. It seems to only happen to custom sysctls that I add. This > happens on multiple machines, but the output in this email is from the > bhyve VM I test in. Any insight as to where my implementation went wrong > would be extremely helpful. > > Full Source: ("make" should compile on a bsd system) > https://github.com/ashaferian/sysctls > > echo_modevent () > { > ... > /* working sysctl using default handler sysctl_handle_int */ > SYSCTL_ADD_PROC(&ctx, SYSCTL_CHILDREN(poid), OID_AUTO, "default", CTLTYPE_INT|CTLFLAG_RW, &ret, -1, sysctl_handle_int, "I", "working sysctl"); > > /* broken sysctl using my handler */ > SYSCTL_ADD_PROC(&ctx, SYSCTL_CHILDREN(poid), OID_AUTO, "custom", > CTLTYPE_INT|CTLFLAG_RW, &ret, -1, sysctl_handle, "I", "working > sysctl"); > } > > static int > sysctl_handle(SYSCTL_HANDLER_ARGS) > { > int error; > > /* returns ENOMEM */ > error = sysctl_handle_int(oidp, arg1, arg2, req); > ... > > In the code above I use the "sysctl_handle" function to handle requests > to the echo.* sysctls I have created. I create two nodes echo.default > which uses the default handler "sysctl_handle_int", and echo.custom > which uses my "sysctl_handle" function. What confuses me so greatly is > that sysctl_handle is just a wrapper that calls sysctl_handle_int and > passes its arguments without changing anything. There should be no > difference because all I do is call the default handler. echo.default works, > while echo.custom does not. Both functions operate on the same > variables and have pretty much the same SYSCLT_ADD_PROC declaration. > > My best guess: > I've tried to dig around in the debugger (using kgdb) but haven't been > able to find anything. The only difference I noticed while tracing was > that the "oldlenp" field in the sysctl_args struct passed in from > userland was 0 when calling my handler and 8 when calling the default > handler. I am not very familiar with the sysctl implementation, but this > affected the valid length in the sysctl_req which ended up returning > ENOMEM from sysctl_old_user. You can watch/confirm this change in sysctl_req > using the following dtrace one-liner. Its unclear why changing the > sysctl handler would affect the arguments passed to it. Yes, this is most likely cause for your issue. ENOMEM does not have anything with the memory shortage, but with the fact that the oldlen is too short for int copyout. Note that for the int-typed oid, old and new len should be 4 (not 0 and not 8). Why your userspace code passed such length is the question to you. > > --------------------------- > dtrace -n '*::sysctl_handle_int:entry /execname == "sysctl" / { > print(*args[3]); }' > > > // sysctl echo.default > 0 27761 sysctl_handle_int:entry struct sysctl_req { > struct thread *td = 0xfffff8000392f580 > int lock = 0x1 > void *oldptr = 0x7fffffffd69c > size_t oldlen = 0x4 > size_t oldidx = 0 > int (*)() oldfunc = kernel`sysctl_old_user > void *newptr = 0 > size_t newlen = 0 > size_t newidx = 0 > int (*)() newfunc = kernel`sysctl_new_user > size_t validlen = 0x4 > int flags = 0 > } > 0 27761 sysctl_handle_int:entry struct sysctl_req { > struct thread *td = 0xfffff8000392f580 > int lock = 0x1 > void *oldptr = 0 > size_t oldlen = 0 > size_t oldidx = 0 > int (*)() oldfunc = kernel`sysctl_old_user > void *newptr = 0 > size_t newlen = 0 > size_t newidx = 0 > int (*)() newfunc = kernel`sysctl_new_user > size_t validlen = 0 > int flags = 0 > } > 0 27761 sysctl_handle_int:entry struct sysctl_req { > struct thread *td = 0xfffff8000392f580 > int lock = 0x1 > void *oldptr = 0x800668000 > size_t oldlen = 0x8 > size_t oldidx = 0 > int (*)() oldfunc = kernel`sysctl_old_user > void *newptr = 0 > size_t newlen = 0 > size_t newidx = 0 > int (*)() newfunc = kernel`sysctl_new_user > size_t validlen = 0x8 > int flags = 0 > } > > // sysctl echo.custom > Custom Sysctl: Error 0 > Custom Sysctl: Error 12 > CPU ID FUNCTION:NAME > 1 27761 sysctl_handle_int:entry struct sysctl_req { > struct thread *td = 0xfffff8000392f580 > int lock = 0x1 > void *oldptr = 0x7fffffffd69c > size_t oldlen = 0x4 > size_t oldidx = 0 > int (*)() oldfunc = kernel`sysctl_old_user > void *newptr = 0 > size_t newlen = 0 > size_t newidx = 0 > int (*)() newfunc = kernel`sysctl_new_user > size_t validlen = 0x4 > int flags = 0 > } > 1 27761 sysctl_handle_int:entry struct sysctl_req { > struct thread *td = 0xfffff8000392f580 > int lock = 0x1 > void *oldptr = 0 > size_t oldlen = 0 > size_t oldidx = 0 > int (*)() oldfunc = kernel`sysctl_old_user > void *newptr = 0 > size_t newlen = 0 > size_t newidx = 0 > int (*)() newfunc = kernel`sysctl_new_user > size_t validlen = 0 > int flags = 0 > } > 1 27761 sysctl_handle_int:entry struct sysctl_req { > struct thread *td = 0xfffff8000392f580 > int lock = 0x1 > void *oldptr = 0x800667008 > size_t oldlen = 0 > size_t oldidx = 0 > int (*)() oldfunc = kernel`sysctl_old_user > void *newptr = 0 > size_t newlen = 0 > size_t newidx = 0 > int (*)() newfunc = kernel`sysctl_new_user > size_t validlen = 0 > int flags = 0 > } > --------------------------- > > I'm really not sure what I've done wrong so any help is greatly > appreciated. Most of the online resources/books that show sysctl > creation seem to do the same thing I did. If there is tricky or > non-obvious behavior that I have missed it would be helpful to note it > for others trying to learn. > > If there is anything else I can provide or do please let me know. > > Thank you so much for your time! > Austin Shafer > > _________________________________________________________________________ > uname -a: > FreeBSD punk-vm 13.0-CURRENT FreeBSD 13.0-CURRENT GENERIC-NODEBUG amd64 > * uname doesn't list revision but it should be r342141 > > top memory usage: > ... > Mem: 20M Active, 2672K Inact, 143M Wired, 98M Buf, 1789M Free > > _______________________________________________ > freebsd-hackers@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-hackers > To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"