[Lcdproc] Problems with CF634 usb

Stewart W. Putnam stewartputnam@comcast.net
Sun May 27 18:58:01 2007


In testing I noticed a difference in behavior between debian sarge and 
debian testing.  I work mostly on sarge with a 2.6.8 kernel and gcc 
3.3.  My test debian etch install uses a 2.6.17 kernel and gcc 4.1.

The difference pertains to the multithreaded behavior in my driver: it's 
creation of multiple threads to send packets; listen for packets; manage 
fans.  Without a long-winded recount of my trial and error fork(), 
clone(), pthread_create() explorations..

On sarge 2.6.8 gcc 3.3 I can open a file as user 0, then do something 
similar to server.c's drop_privs [setuid(user=nobody)] and subsequent 
appends to the file as user=nobody succeed.  Open as root -> drop_privs 
-> continue to write OK.

On etch 2.6.17 gcc 4.1 I got: Open as root -> drop_privs -> 
"user=nobody: write permision denied."  My solution was to drop_privs 
before opening a file and make each thread (listen for packets, send 
packets, manage fans ) drop_privs similarly to maintain identical 
privalages.

The behavior of  fork(), clone(), pthread_create() in inheriting file 
descriptors, signal masks, permissions at fork time -- and wheather 
children automatically sync with changes to these made by the parent -- 
is a complex set of options that at the moment appears to me to have 
changed from sarge 2.6.8 gcc 3.3 to etch 2.6.17 gcc 4.1, likely as 
improved security ... or is it some other configurable option in my 
sarge / etch build environments or init settings ...

This is complex and I'm thinking vaugely about how the one specific 
change I noticed might be analagous to what Brian is finding.

I'd like to see a full / unedited ReportLevel=5 syslog up to and a 
little past the hang from Brian.   Actually two such log reports, one 
done with LCDd.conf [server] "User=nobody" and one with "#User=nobody".  
It would give a detailed look at what wave_to_parent is dooing and show 
wheather the drop_privs part makes any difference.

Or I could be way off in la-la land on this.




Joris Robijn wrote:

>On 26 May 2007 at 20:25, Peter Marschall wrote:
>
>  
>
>>As it was before my time, would you mind to elaborate a bit on the
>>differences (i.e. advantages) of the current code and a simple, dump 
>>daemon() ?
>>    
>>
>
>Usually you set everything up (open tcp port, get things going) and then 
>when it runs you fork. This gives two identical processes of which one is 
>terminated (the parent obviously).
>
>It seems the hardware port access is not inherited by a child process, so 
>the child has to gain the hardware port access (and thus initialization 
>of the drivers) after forking. However, this makes a mess of the messages 
>on the console if things don't go as planned. 
>
>In C terms it looks like below (read the comments). This is from just 
>after the processing of cmdline settings and config file settings and 
>starting the (delayed) report system. 
>
>I have also had a quick glance on some other code in main.c but I can 
>also not find something critical that has changed. I guess we'll have to 
>find out why it does not always work and maybe we'll have to change the 
>way the "wave to parent" is implemented.
>
>Joris
>
>        /* Now, go into daemon mode (if we should)...
>         * We wait for the child to report it is running OK. This 
>mechanism
>         * is used because forking after starting the drivers causes the
>         * child to loose the (LPT) port access. */
>        if (!foreground_mode) {
>                report(RPT_INFO, "Server forking to background");
>                CHAIN(e, parent_pid = daemonize());
>        } else {
>                output_GPL_notice();
>                report(RPT_INFO, "Server running in foreground");
>        }
>        install_signal_handlers(!foreground_mode);
>                /* Only catch SIGHUP if not in foreground mode */
>
>        /* Startup the subparts of the server */
>        CHAIN(e, sock_init(bind_addr, bind_port));
>        CHAIN(e, screenlist_init());
>        CHAIN(e, init_drivers());
>        CHAIN(e, clients_init());
>        CHAIN(e, input_init());
>        CHAIN(e, menuscreens_init());
>        CHAIN(e, server_screen_init());
>        CHAIN_END(e, "Critical error while initializing, abort.");
>        if (!foreground_mode) {
>                /* Tell to parent that startup went OK. */
>                wave_to_parent(parent_pid);
>        }
>        drop_privs(user); /* This can't be done before, because sending a
>                        signal to a process of a different user will fail 
>*/
>
>        do_mainloop();
>        /* This loop never stops; we'll get out only with a signal...*/
>
>        return 0;
>  
>