Flow-IPC 1.0.0
Flow-IPC project: Full implementation reference.
process_credentials.cpp
Go to the documentation of this file.
1/* Flow-IPC: Core
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
20#include <flow/error/error.hpp>
21#include <flow/common.hpp>
22
23namespace ipc::util
24{
25
26// Process_credentials implementations.
27
29 Process_credentials(0, 0, 0)
30{
31 // That's it.
32}
33
35{
36 /* I don't really want to rely on the ordering of this annoying little Linux/whatever structure,
37 * so just assign it manually instead of in the initializer above.
38 * @todo In C++20 can use the { .x = ..., .y = ... } syntax. */
39 m_val.pid = process_id_init;
40 m_val.uid = user_id_init;
41 m_val.gid = group_id_init;
42}
43
46
48{
49 return m_val.pid;
50}
51
53{
54 return m_val.uid;
55}
56
58{
59 return m_val.gid;
60}
61
63{
64 using boost::lexical_cast;
65 using boost::system::system_category;
66 using fs::path;
67 using fs::ifstream;
68 using std::ios_base;
69 using std::string;
70 // using ::errno; // It's a macro apparently.
71
72 FLOW_ERROR_EXEC_AND_THROW_ON_ERROR(std::string, Process_credentials::process_invoked_as, _1);
73 // ^-- Call ourselves and return if err_code is null. If got to present line, err_code is not null.
74
75#ifndef FLOW_OS_LINUX
76# error "process_invoked_as() depends on Linux /proc semantics."
77#endif
78
79 path cmd_line_path("/proc");
80 cmd_line_path /= lexical_cast<path>(process_id());
81 cmd_line_path /= "cmdline";
82
83 /* This weird "file" (I believe it's really the kernel just pumping out these characters, as we read, as opposed
84 * to anything actually being stored on a drive) is argv[0], argv[1], ..., right in a row, each one NUL-terminated.
85 * So open in binary mode and just read up to NUL or end-of-file (EOF). */
86 ifstream cmd_line_file(cmd_line_path, ios_base::binary);
87 if (!cmd_line_file.good())
88 {
89 *err_code = Error_code(errno, system_category());
90 return string();
91 }
92 // else
93
94 /* From this point on we are quite tolerant; we only emit an error if we see the file in non-.good() state --
95 * but only if it's not end-of-file. Beyond that we make zero assumptions about what might be in here (spaces?
96 * EOF without NUL? whatever!); see background in our doc header impl section. Even an empty return value
97 * is not, in itself, an error (see our contract).
98 *
99 * Detail: We could use .getline(), but I don't want to deal with assumptions of max-length.
100 * We could use string<<, but isspace() has locale implications, and I just don't wanna get into all that.
101 * Reading one char at a time from a buffered stream should be fine perf-wise in this context. */
102 string result;
103 bool done = false;
104 do
105 {
106 const int ch_or_none = cmd_line_file.get();
107 if (!(done = (!cmd_line_file.good()) || (char(ch_or_none) == '\0')))
108 {
109 result += ch_or_none;
110 }
111 // else { We break out of loop. }
112 }
113 while (!done);
114
115 if ((!cmd_line_file.good()) && (!cmd_line_file.eof()))
116 {
117 assert((errno != 0) && "There had to be *some* reason file reading failed, and it wasn't EOF.");
118 *err_code = Error_code(errno, system_category());
119 return string();
120 }
121 // else
122
123 return result; // Might still be empty (unlikely though)... but as noted -- that's OK by us.
124} // Process_credentials::process_invoked_as()
125
127{
128 return ::getpid();
129}
130
132{
133 return ::geteuid();
134}
135
137{
138 return ::getegid();
139}
140
142{
144}
145
147{
148 return (val1.process_id() == val2.process_id())
149 && (val1.user_id() == val2.user_id()) && (val1.group_id() == val2.group_id());
150}
151
153{
154 return !operator==(val1, val2);
155}
156
157std::ostream& operator<<(std::ostream& os, const Process_credentials& val)
158{
159 return os << "pid[" << val.process_id() << "], user[" << val.user_id() << ':' << val.group_id() << ']';
160}
161
162} // namespace ipc::util
A process's credentials (PID, UID, GID as of this writing).
process_id_t process_id() const
The process ID (PID).
static process_id_t own_process_id()
Obtains the calling process's process_id().
Process_credentials()
Default ctor: each value is initialized to zero or equivalent.
static Process_credentials own_process_credentials()
Constructs and returns Process_credentials containing values pertaining to the calling process at thi...
::ucred m_val
The raw data. By using Linux ucred directly, we can reuse this as base for Opt_peer_process_credentia...
Process_credentials & operator=(const Process_credentials &src)
Methods.
static user_id_t own_user_id()
Obtains the calling process's effective user_id().
static group_id_t own_group_id()
Obtains the calling process's effective group_id().
user_id_t user_id() const
The user ID (UID).
std::string process_invoked_as(Error_code *err_code=0) const
Obtains, from the OS, information as to the binary name via which process process_id() was started,...
group_id_t group_id() const
The group user ID (GID).
Flow-IPC module containing miscellaneous general-use facilities that ubiquitously used by ~all Flow-I...
::pid_t process_id_t
Syntactic-sugary type for POSIX process ID (integer).
Definition: util_fwd.hpp:137
std::ostream & operator<<(std::ostream &os, const Native_handle &val)
Prints string representation of the given Native_handle to the given ostream.
::gid_t group_id_t
Syntactic-sugary type for POSIX group ID (integer).
Definition: util_fwd.hpp:143
::uid_t user_id_t
Syntactic-sugary type for POSIX user ID (integer).
Definition: util_fwd.hpp:140
bool operator!=(Native_handle val1, Native_handle val2)
Negation of similar ==.
bool operator==(Native_handle val1, Native_handle val2)
Returns true if and only if the two Native_handle objects are the same underlying handle.
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:297