That annoying file descriptor leak that snuck into 3.0.17 has finally been laid to rest. A few double free issues were fixed as I spent quite a long time staring at the same code, till enlightenment hit me like a clue bat. Along with that, there are a bunch of quickfixes for 5.3 quirks. I'm not happy with those, but this is the 3_0 stable branch and by the time 5.3 is popular enough the HEAD should be taking care of those problems. The build is broken in VC++ in this release, but excluding apc_pool.c from the build should work.
Expect more changes... as soon as I get back home.
--Delay always breeds danger and to protract a great design is often to ruin it.
-- Miguel De Cervantes
Another day passes, so what if it was my birthday?
Maybe tomorrow's yours and the world won't care either way.
^Z ^z^z^z ...
--Who will take care of the world after you're gone?
For most of April, I've been on the road. Late night rides all around town, through inner ring road and cubbon, chugging along on my new bike. The weather's been brilliant and I was out, just cruising along the roads, like in a dream.
Yup, I went and splurged on a brand spanking new Royal Enfield Thunderbird. Full 350 cc, 18 BHP of raw petrol power, purring along like a kitten at full throttle, but whisper quiet in idle. For such a heavy bike, it is surprisingly easy to handle, taking bottom heavy curves on turns and excellent stability at speeds. The bike's behaved pretty well so far, the first full tank of petrol lasted me for around 600 Kms. And for once, I'm actually riding a bike made for someone six feet plus. In short, I love it.
The nights are long and the roads are empty
The world's sleeping and
nobody's watching
And the wind whispered to me; keep on driving.
If you worried about falling off the bike, you’d never get on.
-- Lance Armstrong
There's a certain cultural bankruptcy which shows itself in sequels. It indicates, that you're reduced to imitating yourself. But this isn't that kind of a sequel. No, not the kind where there are T Rexes in the city, trying to make a living drawing cartoons or Arnie switching from ammo boxes to ballots. This is the kind which gives a New Hope.
Yesterday, I had an outpouring of hate against the linux capability model. But the problem turned out to be that setuid resets all the capabilites. In hindsight that makes a lot of sense, but didn't even strike until the kernel people (y! has those too) got involved (and I didn't RTFM).
Enter Prctl: The solution was to use the prctl() call with PR_SET_KEEPCAPS to ensure that the capabilities are not discarded when the effective user-id of a process is changed. But, even then, only the CAP_PERMITTED flags are retained and the CAP_EFFECTIVE are masked to zeros.
So, with the prctl call and another cap_set_proc to reset CAP_EFFECTIVE, it was on a roll. Here's the patch on top of unnice.c.
#include <sys/resource.h> +#include <sys/prctl.h>; @@ -26,12 +27,14 @@ if(!fork()) { + prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); /* child */ if(setuid(nobody_uid) < 0) { perror("setuid"); } + cap_set_proc(lcap); if(setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0) - 1) < 0)
Thus concludes this adventure and hope that this blog entry serves as warning of things to come. Watch this space for more Tales! Of! INTEREST!.
--Only great masters of style can succeed in being obtuse.
Running infinte loops is a tricky challenge. What happens to a process when a programmer writes an infinite loop, should be familiar to all. But the challenge is to not let that affect the *other* processes. There seemed to be a perfect solution to it - setrlimit().
The function lets you set soft and hard limits on CPU, so that if a process does exceed the soft limit CPU usage, a SIGXCPU is raised. The process can catch the signal and do something sensible. Basically, all that was required was for the process to call setpriority and let the linux process scheduler slow it down to a trickle.
But a process can lower its priority, but not raise it - if it is a non-privileged process. But linux capabilities allows you to grant CAP_SYS_NICE to the process which essentially lets a non-privileged process muck around with priority - down and up.
To begin with /proc/sys/kernel/cap-bound is unbelievably confusing to use. It is a 32 wide bit-mask on which the 23rd bit apparently seems to be the CAP_SYS_NICE value. After much mucking around, I came to the conclusion that "-257" would be 0xFFFFFEFF which only disables CAP_SETPCAP. But even then the setpriority call kept failing. Here's my test code.
cap_t lcap; const unsigned cap_size = 1; cap_value_t cap_list[] = {CAP_SYS_NICE}; lcap=cap_get_proc(); cap_set_flag(lcap, CAP_EFFECTIVE, cap_size, cap_list, CAP_SET); cap_set_flag(lcap, CAP_PERMITTED, cap_size, cap_list, CAP_SET); cap_set_proc(lcap); if(setuid(nobody_uid) < 0) perror("setuid"); if(setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0) - 1) < 0) perror("setpriority");
Here's a link to the test case in a more compileable condition. Build it with gcc -lcap and run with sudo to test it. Right now, my ubuntu (2.6.22) errors out with this message.
bash$ gcc -lcap -o unnice unnice.c bash$ sudo ./unnice 0: =ep cap_setpcap-ep setpriority: Permission denied
The core issue has to do with apache child-process lifetimes. The only recourse for me is to kill the errant process after the bad infinite loop and have the parent process spawn a new process with a normal priority. But which means blowing off nearly all the local process cache, causing memory churn and more than that, the annoyance of a documented feature not working.
This story currently has no ending, but if any kernel hackers are reading this and should happen to know an answer, please email gopalv shift+2 php noshift+> net. And thus we prepare for a sequel (hopefully).
--I use technology in order to hate it more properly.
-- Nam June Paik
Flaws are inherent in the makings of a hero. For a perfect canditate for heroic tasks would be a man made out of stone - cruel, rational and unemotional. But only cruel to be kind, rational to the core and unstirred by emotional pulls. But who would want to call him a hero?
Over the last two days, I slowly trawled my way through the twelve issue paperback of Watchmen. It has proven to be an interesting comic to peruse.
The book is a continous dismantling of the word "hero". More appropriately, of the super-hero genre - the take-no-lives, nobody-got-hurt-but-the-criminals world of the original heroes. But having accepted collateral damage as a way of life, for the super hero, the question remains - how far will you go to save humanity?.
For your own good: More interesting is the dissection of the purpose of authority. The question hangs in the air - "Who are we protecting them from?". And only the comedian dares answer, but with mirth - "From themselves". Is a nice concept, that few will suffer for the good of many. But that line having been crossed, decisions get mired in a subjective quagmire of the value of a life against another. And it evades the other question - what happens to those who dispense with justice?
quis custodiet ipsos custodes: Ah, but who will watch the watchmen. And even if benevolent they be, what if they take the path piled with corpses. The entire book is a critque on the hypocrisy of authority, the few who are not accountable to any. After all, as I've noticed, in a fair world intentions do not matter.
The book leaves you doubtful how to interpret the shades of grey in people. But at least that's why Rorschach has only black or white - never any gray, on his face. Perhaps to him, it's all black'nwhite.
Perhaps, the real hero is a monster who's cruel to be kind. Amen.
--God instructs the heart, not by ideas, but by pains and contradictions.
-- De Caussade