successfully. Specifically, no error is returned when a file descriptor is attempted to be stored using
<varname>FDSTORE=1</varname> but the service is not actually configured to permit storing of file
descriptors (see above).</para>
+
+ <refsect2 id='errors'>
+ <title>Errors</title>
+
+ <para>Returned errors may indicate the following problems:</para>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>-E2BIG</constant></term>
+
+ <listitem><para>More file descriptors passed at once than the system allows. On Linux the number of
+ file descriptors that may be passed across <constant>AF_UNIX</constant> sockets at once is 253, see
+ <citerefentry
+ project='man-pages'><refentrytitle>unix</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+ details.</para>
+
+ <xi:include href="version-info.xml" xpointer="v257"/></listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
</refsect1>
<refsect1>
#ifndef IPV6_RECVFRAGSIZE
#define IPV6_RECVFRAGSIZE 77
#endif
+
+/* The maximum number of fds that SCM_RIGHTS accepts. This is an internal kernel constant, but very much
+ * useful for userspace too. It's documented in unix(7) these days, hence should be fairly reliable to define
+ * here. */
+#ifndef SCM_MAX_FD
+#define SCM_MAX_FD 253U
+#endif
assert_return(state, -EINVAL);
assert_return(fds || n_fds == 0, -EINVAL);
+ /* Let's make sure the multiplications below don't overflow, and also return a recognizable error in
+ * case the caller tries to send more fds than the kernel limit. The kernel would return EINVAL which
+ * is not too useful I'd say. */
+ if (n_fds > SCM_MAX_FD)
+ return -E2BIG;
+
const char *e = getenv("NOTIFY_SOCKET");
if (!e)
return 0;
r = sd_pid_notify_with_fds(arg_pid.pid, /* unset_environment= */ false, msg, a, k);
}
+ if (r == -E2BIG)
+ return log_error_errno(r, "Too many file descriptors passed.");
if (r < 0)
return log_error_errno(r, "Failed to notify init system: %m");
if (r == 0)