Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Oct 2011 18:54:15 +0200
From:      "Christopher J. Ruwe" <cjr@cruwe.de>
To:        Fabian Keil <freebsd-listen@fabiankeil.de>
Cc:        freebsd-questions@freebsd.org
Subject:   Re: trying to learn systems programming, fear I have not understood and thus messed up
Message-ID:  <20111022185415.25c76aa1@dijkstra>
In-Reply-To: <20111022164508.0dcca5aa@fabiankeil.de>
References:  <20111021185333.7c197a2a@dijkstra> <20111022160453.35dac1f3@dijkstra> <20111022164508.0dcca5aa@fabiankeil.de>

next in thread | previous in thread | raw e-mail | index | archive | help
--Sig_/i_Peww_JkuUJ+X7Usz89t1h
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: quoted-printable

On Sat, 22 Oct 2011 16:45:08 +0200
Fabian Keil <freebsd-listen@fabiankeil.de> wrote:

> "Christopher J. Ruwe" <cjr@cruwe.de> wrote:
>=20
> > On Fri, 21 Oct 2011 18:53:33 +0200
> > "Christopher J. Ruwe" <cjr@cruwe.de> wrote:
> >=20
> > > [...]
> > >=20
> > > I have tried to follow the suggestion from the comment by
> > > modifiying the else-statement thus:
> > >=20
> > > } else {
> > >   struct passwd *trgpwd;
> > >   if (!(trgpwd =3D GETPWNAM(arg->val)))
> > >      errx(EX_DATAERR, "User %s does not exist", arg->val);
> > >   =20
> > >    if (strcmp(a_name->val,"root") =3D=3D 0)
> > >       errx(EX_DATAERR, "can't change uid of `root' account");
> > >    if (strcmp(trgpwd->pw_name, "root") =3D=3D 0)
> > >       warnx("WARNING: account `%s' will have a uid of 0 (superuser
> > > access!)", pwd->pw_name);
> > >=20
> > >    pwd->pw_uid =3D (uid_t) (trgpwd->pw_uid);		   =20
> > >    edited =3D 1;
> > > }=20
> > >=20
> > > What happens is not what I intended. I invoke as "sudo ./pw
> > > usermod testuser1 -u testuser2". I can get testuser2's pwd-entry
> > > by GETPWNAM allright, but when I assign the pw_uid, so as to make
> > > testuser2's uid the same as testuser1's and imgaining to retain
> > > all other values, ./pw reports "pw: user 'testuser2' disappeared
> > > during update" and the testuser2's /etc/passwd entry is replaced
> > > by testuser1's.
> > >=20
> > > I fear I have not understood GETPWNAM correctly, as it seems to
> > > replace the struct pwd as some sort of sideeffect. I could
> > > manually set all pwd-members to the correct ones (those of
> > > testuser2), but I fear that I have messed something up beforehand.
> > >=20
> > > I am grateful for any suggestions and/or correction.=20
> >=20
> > It seems I have indeed not understood GETPWNAM correctly. I have
> > worked out a method which works by calling GETPWNAM twice:
> >=20
> >    else {
> >    /*
> >     * operation as follows:
> >     * a_name->val is passed as usermod <uname>
> >     * arg->val is passed as -u <uname>
> >     *
> >     * first check if we do someting stupid, i.e., want
> >     * to set root uid to some other users uid or
> >     * to set some user accout's uid to root uid.
> >     * then get pwd to that of uname passed as -u <uname>.
> >     * store uid from that pwdent.
> >     * get pwd to that of uname passed as usermod <uname>
> >     * change uid of that latter uid to the one stored
> >     */
> > 		   =20
> >     if(strcmp(a_name->val,"root") =3D=3D 0)
> >       errx(EX_DATAERR, "can't change uid of `root' account");
> >=20
> >     if(strcmp(arg->val, "root") =3D=3D 0)
> >       warnx("WARNING: account `%s' will have a uid of 0 (superuser
> >     access!)", pwd->pw_name);
> >=20
> >     if(!(pwd =3D GETPWNAM(arg->val))) /* -u <uname>*/
> >       errx(EX_DATAERR, "User %s does not exist", arg->val);
> >     int alias_uid =3D pwd->pw_uid;=20
> >=20
> >     if(!(pwd =3D GETPWNAM(a_name->val))) /*usermod <uname>*/
> >       errx(EX_DATAERR, "User %s does not exist", a_name->val);
> >=20
> >     pwd->pw_uid =3D (uid_t) alias_uid;
> >         warnx("User %s's uid changed to %d", pwd->pw_name,
> > pwd->pw_uid); edited =3D 1;
> >   }
> >=20
> > As I stil do not know why the latter variant of my code worked and
> > the former does not, I would still appreciate any comment or
> > explanation which would help me understanding GETPWNAM and getpwnam.
>=20
> I'm not familiar with the code you're working with,
> but according to the man page getpwnam() isn't thread
> safe so you probably shouldn't mess with the returned
> pointer in the first place and only treat the one
> returned by the last call as valid.
>=20
> Did you try using getpwnam_r() instead?
>=20
> Fabian

You are quite right, GETPWNAM() is a macro to getpwnam(), which is not
thread safe. GETPWNAM() is called throughout the code of pw and pw
itself is not threaded, so it should not matter whether the functions
called are thread-safe or not. I am not completely sure on my last
statement though. Do you have other experience regarding this topic?

Anyways, thanks and cheers,
--=20
Christopher J. Ruwe
TZ GMT + 2


--Sig_/i_Peww_JkuUJ+X7Usz89t1h
Content-Type: application/pgp-signature; name=signature.asc
Content-Disposition: attachment; filename=signature.asc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (FreeBSD)

iQIcBAEBAgAGBQJOovU9AAoJEJTIKW/o3iwULK0P/0yxEiCqiXb8Tr+APOvJ7sIB
uR3JowxukyY2k8HaIjzQ5FEEieFjrH8/egcBPA5EPz9cTVO1aZieVXljb7s51TVb
uE7+vRifybYJrTL2NPiLP8xCdEc5S93isOjKcViSWW0anFgO2+QSnKDBhRe1trP9
MMEPidCQ1WrKy3JCHJ+10Wk8MwttuE04n+dET+66lqXRcXPyvRzuVTBIufFrXVIF
9+Nx1z/bi3BG228mCYfkidS7kFWNM7tNVDXIwqekU8PWYPoCVMaOWclHSfRYEqcK
0yITYITV7EYIQxG4wjAcNrqHsNgaH5CsK7HpyzKP6CE3gG5zSqMoHWV5L6QdwG7f
AOTcYxAvpBd5IzMmiHXDfRvIP6XDms5SHpM4e+DItWnSc/1bF4bzw1wt25dv9hKI
BIFX9+wGPDDUXXa3hs8Ijns0oWijJyTd7ZjvOuq/Bz+wuTzKIlYAKaCOCJLcGBDO
W1Z2azIMt7Ef/Yn73GC02lLbCneVS55rSsg6v3QCH6wMrMe6a1CN1KDJLUkmKjFx
ixHDqY1TvIrrnDjYZBjZo3LBwI5z57HuLkBNZklXq3YgzTnLpp/RAuNw9LZyAssj
OXVWlQl2STcWhKvHyScJssWDI9HKhc4ZDRYNjoh7yqIILDuZP0fV64gMrJWesJYQ
H5EhEIk/q13zRFdsPv7y
=Np8/
-----END PGP SIGNATURE-----

--Sig_/i_Peww_JkuUJ+X7Usz89t1h--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20111022185415.25c76aa1>