From owner-freebsd-hackers@freebsd.org Mon Dec 17 22:34:07 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 14314134DF07 for ; Mon, 17 Dec 2018 22:34:07 +0000 (UTC) (envelope-from amshafer64@gmail.com) Received: from mail-qk1-x742.google.com (mail-qk1-x742.google.com [IPv6:2607:f8b0:4864:20::742]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "Google Internet Authority G3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 56CC98D644 for ; Mon, 17 Dec 2018 22:34:06 +0000 (UTC) (envelope-from amshafer64@gmail.com) Received: by mail-qk1-x742.google.com with SMTP id r71so8362977qkr.10 for ; Mon, 17 Dec 2018 14:34:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:mime-version; bh=aULCV7AmjhrdpVlVl7KyUldt6Vw046LrRzjFY+dXoaw=; b=KjW2dtEP1t9tx9YJcdK37Hj34oR9LmdDH72w9YkMyIr1C+v4HMB2d9W9A2cWrhFsa0 BJQz4NcNa+hUFawiAWIK7yE3e+U3vfML44WvYoywVuONP/BOFAQiwycELqiv3cFeWXaB RuzAAT0uUo94SpIjEEm0ea4NYe9iifbAC4HENC2nxlcV29L82aQmfL2U2QEeAVCIyzGZ ibBQhcch2FeK1D7AIYbzG+LaymMFTBuwjCwsMI9+EGmtAl8Rx6tPQs5jJQOWf3b5NEHz md9FcoDoRme9NOgTPw3bfRVQT94kMezNVcthoun1/Gq2/D4CbDhaFhMyA91QNUF3nE5W IrSA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version; bh=aULCV7AmjhrdpVlVl7KyUldt6Vw046LrRzjFY+dXoaw=; b=FEUqVnYiVQeW/CXoAo6uxssQyF4GH+gzpEY8liHr8fF9zOxV+kdSD7AxH8uhHU5nXq 7P4uAE51UYAQqLOGxGAjgAEPvnjTR5YPfc1lhdi/WUrU51VXj/Gn/QDFFG4Qq9TmBAx/ qZM+/r1HAoGk7pNu8btD+pFeVFGcHf+wQe+2flrc+/bCF3yEizBtm//1nyoJkaLVvoLx y09SZJLW5pKFUf/sKhslDjMAfn1w1zSxHI6hQtdMrgMeBH5Ph0rUeqjRDjWmIIrZKlu5 p7mbsOUYRWvrijQOTsxrUetxoyU6NTuKRlUj7GxhXFpxfHF4DpCnWBFW7yb1lsq0J1Fo s3ow== X-Gm-Message-State: AA+aEWYdFq1AH+EQotuz84hr1n3VYuCoUWdhuNBE6tw0vbi88owwWskc gTqrF9Z3re9yU4z6Nw9Zf7PGJHvv X-Google-Smtp-Source: AFSGD/VypHuirSPr6cbv0MblfyWPdotB6b0oHiaXyfaMqPDLUapk5Z0yOzhuoo3jd37tt+kqFXFWwg== X-Received: by 2002:a37:5257:: with SMTP id g84mr14048509qkb.76.1545086045629; Mon, 17 Dec 2018 14:34:05 -0800 (PST) Received: from localhost ([178.128.156.9]) by smtp.gmail.com with ESMTPSA id 83sm8338142qkz.73.2018.12.17.14.34.04 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Dec 2018 14:34:05 -0800 (PST) From: Austin Shafer To: freebsd-hackers@freebsd.org Subject: ENOMEM when calling sysctl_handle_int from custom handler Date: Mon, 17 Dec 2018 17:34:05 -0500 Message-ID: <861s6fpyua.fsf@triplebuff.com> MIME-Version: 1.0 Content-Type: text/plain X-Rspamd-Queue-Id: 56CC98D644 X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org; dkim=pass header.d=gmail.com header.s=20161025 header.b=KjW2dtEP; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (mx1.freebsd.org: domain of amshafer64@gmail.com designates 2607:f8b0:4864:20::742 as permitted sender) smtp.mailfrom=amshafer64@gmail.com X-Spamd-Result: default: False [-2.09 / 15.00]; RCVD_VIA_SMTP_AUTH(0.00)[]; R_SPF_ALLOW(-0.20)[+ip6:2607:f8b0:4000::/36]; FREEMAIL_FROM(0.00)[gmail.com]; TO_DN_NONE(0.00)[]; RCVD_COUNT_THREE(0.00)[3]; MX_GOOD(-0.01)[cached: alt3.gmail-smtp-in.l.google.com]; DKIM_TRACE(0.00)[gmail.com:+]; DMARC_POLICY_ALLOW(-0.50)[gmail.com,none]; FROM_EQ_ENVFROM(0.00)[]; IP_SCORE(0.38)[ip: (5.02), ipnet: 2607:f8b0::/32(-1.69), asn: 15169(-1.37), country: US(-0.08)]; MIME_TRACE(0.00)[0:+]; FREEMAIL_ENVFROM(0.00)[gmail.com]; ASN(0.00)[asn:15169, ipnet:2607:f8b0::/32, country:US]; DWL_DNSWL_NONE(0.00)[gmail.com.dwl.dnswl.org : 127.0.5.0]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-0.96)[-0.962,0]; R_DKIM_ALLOW(-0.20)[gmail.com:s=20161025]; FROM_HAS_DN(0.00)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; NEURAL_HAM_LONG(-0.53)[-0.533,0]; MIME_GOOD(-0.10)[text/plain]; PREVIOUSLY_DELIVERED(0.00)[freebsd-hackers@freebsd.org]; RCPT_COUNT_ONE(0.00)[1]; RCVD_TLS_LAST(0.00)[]; NEURAL_SPAM_SHORT(0.04)[0.036,0]; RCVD_IN_DNSWL_NONE(0.00)[2.4.7.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.4.6.8.4.0.b.8.f.7.0.6.2.list.dnswl.org : 127.0.5.0] 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: Mon, 17 Dec 2018 22:34:07 -0000 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. --------------------------- 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