[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: password file locking



Thanks for clearing up the permanent lockfile idea. It's totally clear
to me how it works now.
As you noted, the power-down-at-the-wrong-time problem can hurt this
approach severely unless, like Fred Cohen suggested, the reading of the
passwd file is done via a special function which checks for the
resulting old passwd file if the new one doesn't appear in time or ever.
While probably a working solution, I think it's *WAY* too much effort
since there are probably a great many apps around that access passwd
directly for reading.

Michael Tokarev wrote:
> 
> Cooper wrote:
> >
> > Okay, alternative approach.
> >
> > Open+lock passwd, read passwd, update data, write passwd.new, rename
> > passwd.new to passwd, close locked passwd.
> >
> > The trick here is that you can't wait for the passwd file to become
> > available to you because once the lock is cleared, the file the lock was
> > on nolonger exists, so you'll have to resort to polling.
> 
> Exactly (but I doesn't understand what "polling" means here).

With polling I mean that you can't wait for the lock to clear using some
blocking call, but instead you need to try to get the lock, and if you
can't get it you need to close the file, open the file and try to get
the lock again. You need to periodically poll the file, checking if
there is a lock.
If a lot of small modifications need to be made to the passwd/shadow
file all the time, there's the possibility that the system spends way
too much time checking for the lock, or waiting for it to be cleared.

> lckpwd() have _no_ races and it have very simple interface:
> 
>   if (lckpwdf() == 0) {
>      do updates
>      unlckpwdf()
>   }

That's just a matter of implementation of the lckpwdf() function.
In the above case the lckpwdf() could be something like:

static int lock_fd(int fd)
{       struct flock lock;

        lock.l_type=F_WRLCK;
        lock.l_whence=SEEK_CUR;
        lock.l_start=(off_t)0;
        lock.l_len=(off_t)0;
        return fcntl(fd,F_SETLKW,&lock);
}

static int get_passwd_lock(int *fd)
{	int result;
	(*fd)=open(filename,O_WRONLY);
	if ((*fd)<0) return -1;
	result=lock_fd(*fd);
	if (result==-1)	close(*fd);
	return result;
}

int lckpwdf(int *fd)
{	int retries=3;
	while (get_passwd_lock(fd)!=0)
	{	sleep(1);
		if ((retries--)==0)
		{	(*fd)=-1;
			return -1;
		}
	}
	return 0;
}

The only problem now is that a poorly written program can take the lock
and keep it as long as it's active. You can however query the lock to
get the pid of the process that has the lock so you can act on that too.

> No, it is not about heavily updates.  Conflicts are just less frequent
> on "small sites", but them are _exists_ always (unless you only one
> user of the system -- but even in this case you should take care of
> that).

With an implementation similar to what's written above I would think
that the conflict situations are dealt with quite nicely.
The only problem that now remains is that the old passwd file will be
lost after the rename because AFAIK you can't assign a new filename to
an open filedescriptor. You could open the file in O_RDWR in the
get_passwd_lock function, and after the rename read out the file and
with that data update the passwd.old file in a similar, or more brutal
fashion. I think that's a small price to pay for always having a passwd
file available.

Cooper
-- 
If you can read this you're probably not dead yet.
	- Johnny The Homicidal Maniac 7 -





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []