Xosphinx.addnodesdocument)}( rawsourcechildren]( translations LanguagesNode)}(hhh](h pending_xref)}(hhh]docutils.nodesTextChinese (Simplified)}parenthsba attributes}(ids]classes]names]dupnames]backrefs] refdomainstdreftypedoc reftarget+/translations/zh_CN/bpf/prog_cgroup_sockoptmodnameN classnameN refexplicitutagnamehhh ubh)}(hhh]hChinese (Traditional)}hh2sbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/zh_TW/bpf/prog_cgroup_sockoptmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hItalian}hhFsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/it_IT/bpf/prog_cgroup_sockoptmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hJapanese}hhZsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/ja_JP/bpf/prog_cgroup_sockoptmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hKorean}hhnsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/ko_KR/bpf/prog_cgroup_sockoptmodnameN classnameN refexplicituh1hhh ubh)}(hhh]hSpanish}hhsbah}(h]h ]h"]h$]h&] refdomainh)reftypeh+ reftarget+/translations/sp_SP/bpf/prog_cgroup_sockoptmodnameN classnameN refexplicituh1hhh ubeh}(h]h ]h"]h$]h&]current_languageEnglishuh1h hh _documenthsourceNlineNubhcomment)}(h SPDX-License-Identifier: GPL-2.0h]h SPDX-License-Identifier: GPL-2.0}hhsbah}(h]h ]h"]h$]h&] xml:spacepreserveuh1hhhhhhE/var/lib/git/docbuild/linux/Documentation/bpf/prog_cgroup_sockopt.rsthKubhsection)}(hhh](htitle)}(hBPF_PROG_TYPE_CGROUP_SOCKOPTh]hBPF_PROG_TYPE_CGROUP_SOCKOPT}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhhhhhKubh paragraph)}(hR``BPF_PROG_TYPE_CGROUP_SOCKOPT`` program type can be attached to two cgroup hooks:h](hliteral)}(h ``BPF_PROG_TYPE_CGROUP_SOCKOPT``h]hBPF_PROG_TYPE_CGROUP_SOCKOPT}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhubh2 program type can be attached to two cgroup hooks:}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh bullet_list)}(hhh](h list_item)}(hZ``BPF_CGROUP_GETSOCKOPT`` - called every time process executes ``getsockopt`` system call.h]h)}(hZ``BPF_CGROUP_GETSOCKOPT`` - called every time process executes ``getsockopt`` system call.h](h)}(h``BPF_CGROUP_GETSOCKOPT``h]hBPF_CGROUP_GETSOCKOPT}(hhhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhubh& - called every time process executes }(hhhhhNhNubh)}(h``getsockopt``h]h getsockopt}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1hhhubh system call.}(hhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hhubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubh)}(h[``BPF_CGROUP_SETSOCKOPT`` - called every time process executes ``setsockopt`` system call. h]h)}(hZ``BPF_CGROUP_SETSOCKOPT`` - called every time process executes ``setsockopt`` system call.h](h)}(h``BPF_CGROUP_SETSOCKOPT``h]hBPF_CGROUP_SETSOCKOPT}(hj0hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj,ubh& - called every time process executes }(hj,hhhNhNubh)}(h``setsockopt``h]h setsockopt}(hjBhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj,ubh system call.}(hj,hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK hj(ubah}(h]h ]h"]h$]h&]uh1hhhhhhhhNubeh}(h]h ]h"]h$]h&]bullet*uh1hhhhK hhhhubh)}(hThe context (``struct bpf_sockopt``) has associated socket (``sk``) and all input arguments: ``level``, ``optname``, ``optval`` and ``optlen``.h](h The context (}(hjhhhhNhNubh)}(h``struct bpf_sockopt``h]hstruct bpf_sockopt}(hjphhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhubh) has associated socket (}(hjhhhhNhNubh)}(h``sk``h]hsk}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhubh) and all input arguments: }(hjhhhhNhNubh)}(h ``level``h]hlevel}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhubh, }(hjhhhhNhNubh)}(h ``optname``h]hoptname}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhubh, }hjhsbh)}(h ``optval``h]hoptval}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhubh and }(hjhhhhNhNubh)}(h ``optlen``h]hoptlen}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhubh.}(hjhhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhhhhubh)}(hhh](h)}(hBPF_CGROUP_SETSOCKOPTh]hBPF_CGROUP_SETSOCKOPT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhKubh)}(h``BPF_CGROUP_SETSOCKOPT`` is triggered *before* the kernel handling of sockopt and it has writable context: it can modify the supplied arguments before passing them down to the kernel. This hook has access to the cgroup and socket local storage.h](h)}(h``BPF_CGROUP_SETSOCKOPT``h]hBPF_CGROUP_SETSOCKOPT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh is triggered }(hjhhhNhNubhemphasis)}(h*before*h]hbefore}(hj hhhNhNubah}(h]h ]h"]h$]h&]uh1j hjubh the kernel handling of sockopt and it has writable context: it can modify the supplied arguments before passing them down to the kernel. This hook has access to the cgroup and socket local storage.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hIf BPF program sets ``optlen`` to -1, the control will be returned back to the userspace after all other BPF programs in the cgroup chain finish (i.e. kernel ``setsockopt`` handling will *not* be executed).h](hIf BPF program sets }(hj#hhhNhNubh)}(h ``optlen``h]hoptlen}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj#ubh to -1, the control will be returned back to the userspace after all other BPF programs in the cgroup chain finish (i.e. kernel }(hj#hhhNhNubh)}(h``setsockopt``h]h setsockopt}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj#ubh handling will }(hj#hhhNhNubj )}(h*not*h]hnot}(hjOhhhNhNubah}(h]h ]h"]h$]h&]uh1j hj#ubh be executed).}(hj#hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hNote, that ``optlen`` can not be increased beyond the user-supplied value. It can only be decreased or set to -1. Any other value will trigger ``EFAULT``.h](h Note, that }(hjghhhNhNubh)}(h ``optlen``h]hoptlen}(hjohhhNhNubah}(h]h ]h"]h$]h&]uh1hhjgubhz can not be increased beyond the user-supplied value. It can only be decreased or set to -1. Any other value will trigger }(hjghhhNhNubh)}(h ``EFAULT``h]hEFAULT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjgubh.}(hjghhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhjhhubh)}(hhh](h)}(h Return Typeh]h Return Type}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjhhhhhK#ubh)}(hhh](h)}(hH``0`` - reject the syscall, ``EPERM`` will be returned to the userspace.h]h)}(hjh](h)}(h``0``h]h0}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh - reject the syscall, }(hjhhhNhNubh)}(h ``EPERM``h]hEPERM}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh# will be returned to the userspace.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK%hjubah}(h]h ]h"]h$]h&]uh1hhjhhhhhNubh)}(hE``1`` - success, continue with next BPF program in the cgroup chain. h]h)}(hD``1`` - success, continue with next BPF program in the cgroup chain.h](h)}(h``1``h]h1}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh? - success, continue with next BPF program in the cgroup chain.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK&hjubah}(h]h ]h"]h$]h&]uh1hhjhhhhhNubeh}(h]h ]h"]h$]h&]jfjguh1hhhhK%hjhhubeh}(h] return-typeah ]h"]h$] return typeah&]uh1hhjhhhhhK# referencedKubeh}(h]bpf-cgroup-setsockoptah ]h"]bpf_cgroup_setsockoptah$]h&]uh1hhhhhhhhKubh)}(hhh](h)}(hBPF_CGROUP_GETSOCKOPTh]hBPF_CGROUP_GETSOCKOPT}(hj$hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj!hhhhhK)ubh)}(hX``BPF_CGROUP_GETSOCKOPT`` is triggered *after* the kernel handing of sockopt. The BPF hook can observe ``optval``, ``optlen`` and ``retval`` if it's interested in whatever kernel has returned. BPF hook can override the values above, adjust ``optlen`` and reset ``retval`` to 0. If ``optlen`` has been increased above initial ``getsockopt`` value (i.e. userspace buffer is too small), ``EFAULT`` is returned.h](h)}(h``BPF_CGROUP_GETSOCKOPT``h]hBPF_CGROUP_GETSOCKOPT}(hj6hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh is triggered }(hj2hhhNhNubj )}(h*after*h]hafter}(hjHhhhNhNubah}(h]h ]h"]h$]h&]uh1j hj2ubh9 the kernel handing of sockopt. The BPF hook can observe }(hj2hhhNhNubh)}(h ``optval``h]hoptval}(hjZhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh, }(hj2hhhNhNubh)}(h ``optlen``h]hoptlen}(hjlhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh and }(hj2hhhNhNubh)}(h ``retval``h]hretval}(hj~hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubhf if it’s interested in whatever kernel has returned. BPF hook can override the values above, adjust }(hj2hhhNhNubh)}(h ``optlen``h]hoptlen}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh and reset }(hj2hhhNhNubh)}(h ``retval``h]hretval}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh to 0. If }(hj2hhhNhNubh)}(h ``optlen``h]hoptlen}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh" has been increased above initial }(hj2hhhNhNubh)}(h``getsockopt``h]h getsockopt}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh- value (i.e. userspace buffer is too small), }(hj2hhhNhNubh)}(h ``EFAULT``h]hEFAULT}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj2ubh is returned.}(hj2hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK+hj!hhubh)}(hhhhNhNubah}(h]h ]h"]h$]h&]uh1hhj;hhhhhKZubh)}(hWhen the ``optval`` is greater than the ``PAGE_SIZE``, the BPF program can access only the first ``PAGE_SIZE`` of that data. So it has to options:h](h When the }(hjLhhhNhNubh)}(h ``optval``h]hoptval}(hjThhhNhNubah}(h]h ]h"]h$]h&]uh1hhjLubh is greater than the }(hjLhhhNhNubh)}(h ``PAGE_SIZE``h]h PAGE_SIZE}(hjfhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjLubh,, the BPF program can access only the first }(hjLhhhNhNubh)}(h ``PAGE_SIZE``h]h PAGE_SIZE}(hjxhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjLubh$ of that data. So it has to options:}(hjLhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK[hj;hhubh)}(hhh](h)}(hSet ``optlen`` to zero, which indicates that the kernel should use the original buffer from the userspace. Any modifications done by the BPF program to the ``optval`` are ignored.h]h)}(hSet ``optlen`` to zero, which indicates that the kernel should use the original buffer from the userspace. Any modifications done by the BPF program to the ``optval`` are ignored.h](hSet }(hjhhhNhNubh)}(h ``optlen``h]hoptlen}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh to zero, which indicates that the kernel should use the original buffer from the userspace. Any modifications done by the BPF program to the }(hjhhhNhNubh)}(h ``optval``h]hoptval}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh are ignored.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhK^hjubah}(h]h ]h"]h$]h&]uh1hhjhhhhhNubh)}(hzSet ``optlen`` to the value less than ``PAGE_SIZE``, which indicates that the kernel should use BPF's trimmed ``optval``. h]h)}(hySet ``optlen`` to the value less than ``PAGE_SIZE``, which indicates that the kernel should use BPF's trimmed ``optval``.h](hSet }(hjhhhNhNubh)}(h ``optlen``h]hoptlen}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh to the value less than }(hjhhhNhNubh)}(h ``PAGE_SIZE``h]h PAGE_SIZE}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh=, which indicates that the kernel should use BPF’s trimmed }(hjhhhNhNubh)}(h ``optval``h]hoptval}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKahjubah}(h]h ]h"]h$]h&]uh1hhjhhhhhNubeh}(h]h ]h"]h$]h&]jfjguh1hhhhK^hj;hhubh)}(hWhen the BPF program returns with the ``optlen`` greater than ``PAGE_SIZE``, the userspace will receive original kernel buffers without any modifications that the BPF program might have applied.h](h&When the BPF program returns with the }(hj#hhhNhNubh)}(h ``optlen``h]hoptlen}(hj+hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj#ubh greater than }(hj#hhhNhNubh)}(h ``PAGE_SIZE``h]h PAGE_SIZE}(hj=hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj#ubhw, the userspace will receive original kernel buffers without any modifications that the BPF program might have applied.}(hj#hhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKdhj;hhubeh}(h] large-optvalah ]h"] large optvalah$]h&]uh1hhhhhhhhKZubh)}(hhh](h)}(hExampleh]hExample}(hj`hhhNhNubah}(h]h ]h"]h$]h&]uh1hhj]hhhhhKjubh)}(h5Recommended way to handle BPF programs is as follows:h]h5Recommended way to handle BPF programs is as follows:}(hjnhhhNhNubah}(h]h ]h"]h$]h&]uh1hhhhKlhj]hhubj0)}(hX(SEC("cgroup/getsockopt") int getsockopt(struct bpf_sockopt *ctx) { /* Custom socket option. */ if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) { ctx->retval = 0; optval[0] = ...; ctx->optlen = 1; return 1; } /* Modify kernel's socket option. */ if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) { ctx->retval = 0; optval[0] = ...; ctx->optlen = 1; return 1; } /* optval larger than PAGE_SIZE use kernel's buffer. */ if (ctx->optlen > PAGE_SIZE) ctx->optlen = 0; return 1; } SEC("cgroup/setsockopt") int setsockopt(struct bpf_sockopt *ctx) { /* Custom socket option. */ if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) { /* do something */ ctx->optlen = -1; return 1; } /* Modify kernel's socket option. */ if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) { optval[0] = ...; return 1; } /* optval larger than PAGE_SIZE use kernel's buffer. */ if (ctx->optlen > PAGE_SIZE) ctx->optlen = 0; return 1; }h]hX(SEC("cgroup/getsockopt") int getsockopt(struct bpf_sockopt *ctx) { /* Custom socket option. */ if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) { ctx->retval = 0; optval[0] = ...; ctx->optlen = 1; return 1; } /* Modify kernel's socket option. */ if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) { ctx->retval = 0; optval[0] = ...; ctx->optlen = 1; return 1; } /* optval larger than PAGE_SIZE use kernel's buffer. */ if (ctx->optlen > PAGE_SIZE) ctx->optlen = 0; return 1; } SEC("cgroup/setsockopt") int setsockopt(struct bpf_sockopt *ctx) { /* Custom socket option. */ if (ctx->level == MY_SOL && ctx->optname == MY_OPTNAME) { /* do something */ ctx->optlen = -1; return 1; } /* Modify kernel's socket option. */ if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) { optval[0] = ...; return 1; } /* optval larger than PAGE_SIZE use kernel's buffer. */ if (ctx->optlen > PAGE_SIZE) ctx->optlen = 0; return 1; }}hj|sbah}(h]h ]h"]h$]h&]hhforcelanguagechighlight_args}uh1j/hhhKnhj]hhubh)}(hqSee ``tools/testing/selftests/bpf/progs/sockopt_sk.c`` for an example of BPF program that handles socket options.h](hSee }(hjhhhNhNubh)}(h2``tools/testing/selftests/bpf/progs/sockopt_sk.c``h]h.tools/testing/selftests/bpf/progs/sockopt_sk.c}(hjhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjubh; for an example of BPF program that handles socket options.}(hjhhhNhNubeh}(h]h ]h"]h$]h&]uh1hhhhKhj]hhubeh}(h]exampleah ]h"]exampleah$]h&]uh1hhhhhhhhKjubeh}(h]bpf-prog-type-cgroup-sockoptah ]h"]bpf_prog_type_cgroup_sockoptah$]h&]uh1hhhhhhhhKubeh}(h]h ]h"]h$]h&]sourcehuh1hcurrent_sourceN current_lineNsettingsdocutils.frontendValues)}(hN generatorN datestampN source_linkN source_urlN toc_backlinksentryfootnote_backlinksK sectnum_xformKstrip_commentsNstrip_elements_with_classesN strip_classesN report_levelK halt_levelKexit_status_levelKdebugNwarning_streamN tracebackinput_encoding utf-8-siginput_encoding_error_handlerstrictoutput_encodingutf-8output_encoding_error_handlerjerror_encodingutf-8error_encoding_error_handlerbackslashreplace language_codeenrecord_dependenciesNconfigN id_prefixhauto_id_prefixid dump_settingsNdump_internalsNdump_transformsNdump_pseudo_xmlNexpose_internalsNstrict_visitorN_disable_configN_sourceh _destinationN _config_files]7/var/lib/git/docbuild/linux/Documentation/docutils.confafile_insertion_enabled raw_enabledKline_length_limitM'pep_referencesN pep_base_urlhttps://peps.python.org/pep_file_url_templatepep-%04drfc_referencesN rfc_base_url&https://datatracker.ietf.org/doc/html/ tab_widthKtrim_footnote_reference_spacesyntax_highlightlong smart_quotessmartquotes_locales]character_level_inline_markupdoctitle_xform docinfo_xformKsectsubtitle_xform image_loadinglinkembed_stylesheetcloak_email_addressessection_self_linkenvNubreporterNindirect_targets]substitution_defs}substitution_names}refnames}refids}nameids}(jjjj return typeNjjj8j5jZjWjju nametypes}(jjj&jj8jZjuh}(jhjjjjjj!jj0j5jjWj;jj]u footnote_refs} citation_refs} autofootnotes]autofootnote_refs]symbol_footnotes]symbol_footnote_refs] footnotes] citations]autofootnote_startKsymbol_footnote_startK id_counter collectionsCounter}jKsRparse_messages]hsystem_message)}(hhh]h)}(h.Duplicate implicit target name: "return type".h]h2Duplicate implicit target name: “return type”.}(hjJhhhNhNubah}(h]h ]h"]h$]h&]uh1hhjGubah}(h]h ]h"]h$]h&]jalevelKtypeINFOsourcehlineK9uh1jEhj0hhhhhK9ubatransform_messages] transformerN include_log] decorationNhhub.