Bug 238319

Summary: login: Extend and add features to session (struct)
Product: Base System Reporter: jau
Component: kernAssignee: freebsd-bugs (Nobody) <bugs>
Status: Open ---    
Severity: Affects Some People CC: cem
Priority: --- Keywords: feature, needs-patch, security
Version: CURRENT   
Hardware: Any   
OS: Any   

Description jau 2019-06-04 08:25:57 UTC
As already mentioned in the summary this is not actually a bug report per se,
but a proposal to extend the OS with completely new functionality.

- 1st I would like to propose making the session login name field sort of
write-once-read-many (WORM) field when kern.securelevel is above 0.
That would allow setting the login name once for each new session when
it has not been set before. Making it immutable when it has been set
would give he field content quite a lot credibility later for security
related actions or logging.

- 2nd I would like to propose adding a few completely new data items
in the session struct. These would be the address family and source address
for any IPC connections independent of whether it is LOCAL/UNIX or over
a proper network connection. Maybe even the protocol and source port should
be included when applicable. Obviously making such fields WORM similarly
to what I proposed for session login name above would be logical.
The benefit of having such address data available in a reliable manner
later in the session would make it very hard for any user or process to
hide the true origin of the session.
That would further allow for better security related decisions based
on where the session originates.
Maybe some services, their features, or actions should be limited purely
to local users, to users in a certain city, to users in a certain larger
geographic region, to users within a certain country, to users on a certain
continent, or maybe users from within any EU country but not others, etc.

In many cases the application server only inherits a local socket or a pty
from the actual network daemon. Without seeing the actual network socket
the child process has no access to the origin information available through
calls to getpeername() and getsockopt(). This then leads to weird attempts
to pass the true session origin to child processes in environment variables
(e.g SSH_CLIENT) or to other unreliable ad hoc methods to passing on the
information while leaving it in worst case modifiable to an intruder.

In some cases there might have to be distinct versions of the same service
provided to users from distinct origins. In some cases the difference might
be just a display of a different legal notification. In other cases there
might be additional features for users from a certain origin and reduced
features for other.

Number 2 above would naturally make the session struct quite large if
the longest possible local path name would have to fit in for LOCAL
domain origins. OTOH that increase would not cause a serious memory load
because there is only one session struct shared by all processes within
a session. From my point of view such relatively small sacrifice in memory
would be quite reasonable.
Comment 1 Conrad Meyer freebsd_committer freebsd_triage 2019-06-04 15:52:49 UTC
Re: (1):

s_login is only modified by setlogin(2), which requires PRIV_PROC_SETLOGIN, which ... is always permitted for the current process on its session.  Each time it is set, it produces an audit record, AUDIT_ARG_LOGIN().

You could conceivably add a flag to session 'has_login_been_set', set it as appropriate, and check it in priv_check PRIV_PROC_SETLOGIN under securelevel.  But why?

What does it mean to restrict setlogin(2) to "new" sessions?  Users can always just create a new process and make it the new session leader (setsid() or setpgid()).  The old process gets a new "login" on its associated session.

Re: (2):

I don't think this metadata makes much sense in session.  It's out of line with existing session metadata (mostly tracking process group and controlling terminal -- heavily tied to shell login and process groups).  In particular, sessions are a process concept, not a thread one.  There is no guarantee that all httpds follow the model required for this to make sense.

And if you have to fix httpds, you might as well just pass the information to the worker in some side channel; either environment variables, or a pipe, or shared memory segment.

I guess the target network daemon is sshd, which is single threaded, and for that it might work?  But it doesn't really generalize, IMO.