path: root/paludis/util/process.cc
diff options
authorAvatar Saleem Abdulrasool <compnerd@compnerd.org> 2016-01-17 12:21:45 -0800
committerAvatar Saleem Abdulrasool <compnerd@compnerd.org> 2016-01-21 13:09:11 -0800
commit6cc7eb47142dcad1cf277ccf31c38fc53746e45e (patch)
tree6c029356fe6b2a580de4875c1e4201e4881deea9 /paludis/util/process.cc
parent1e359553c2e5da698318714bd77884da0288f4d8 (diff)
paludis: POSIX_ME_HARDER accounts repository
POSIX permits an indefinite required buffer size for querying GECOS fields. This is currently used in three locations. Previously, paludis would assume that it could perform a sysconf call to retrieve the requisite buffer size for ensuring that the subsequent GECOS field query would not receive a -ERANGE error. However, as it turns out, this is actually a problem even with GLIBC where the NSS may end up querying a service which has a larger field value for the `struct pwd` (glibc sets the return value to the NSS buffer length, aka 1k, but may end up querying a service which provides a larger response). Use local wrappers which perform the size adjustment to avoid an undersized buffer. Localise the functions which query the various GECOS fields which comprise the persona into util.
Diffstat (limited to 'paludis/util/process.cc')
1 files changed, 6 insertions, 8 deletions
diff --git a/paludis/util/process.cc b/paludis/util/process.cc
index b4b553db1..380d671d6 100644
--- a/paludis/util/process.cc
+++ b/paludis/util/process.cc
@@ -17,6 +17,7 @@
* Place, Suite 330, Boston, MA 02111-1307 USA
+#include <paludis/util/persona.hh>
#include <paludis/util/process.hh>
#include <paludis/util/pimp-impl.hh>
#include <paludis/util/pipe.hh>
@@ -806,17 +807,14 @@ Process::run()
if (0 != ::setgid(_imp->setgid))
throw ProcessError("setgid() failed");
- int buflen(::sysconf(_SC_GETPW_R_SIZE_MAX));
- if (-1 == buflen)
- buflen = 1 << 16;
+ struct passwd pwd;
+ struct passwd *result;
+ std::vector<char> buffer;
- std::unique_ptr<char []> buf(new char[buflen]);
- struct passwd pw;
- struct passwd * pw_result(nullptr);
- if (0 != getpwuid_r(_imp->setuid, &pw, buf.get(), buflen, &pw_result) || nullptr == pw_result)
+ if (0 != getpwuid_r_s(_imp->setuid, buffer, pwd, result) || result == nullptr)
throw ProcessError("getpwuid_r() failed");
- if (0 != ::initgroups(pw_result->pw_name, getgid()))
+ if (0 != ::initgroups(pwd.pw_name, getgid()))
throw ProcessError("initgroups() failed");
if (0 != ::setuid(_imp->setuid))