BUG:: IPC/semop clobbers PID of the last modifier

Anton Lavrentiev (lavr@ncbi.nlm.nih.gov)
Sat, 13 Apr 2002 02:27:13 -0400 (EDT)


Hi Linus,

I think I found another bug in the kernel. If "wait for zero"
operation on an IPC semaphore is going to be blocked,
it then clobbers (resets to 0) PID of the process, which last
modified the semaphore (obtainable via semctl(...GETPID...)).
This bug is simply because of undo in 'try_atomic_semop' always
restores PID of the last process that modified the semaphore, while
"wait for zero" does not save that PID:

file ipc/sem.c, try_atomic_semop():
---------------------------------------------------------------------------
if (!sem_op && curr->semval) /*!!!!!!*/
goto would_block;

curr->sempid = (curr->sempid << 16) | pid; /*!!!!!!*/

........

would_block:
if (sop->sem_flg & IPC_NOWAIT)
result = -EAGAIN;
else
result = 1;

undo:
while (sop >= sops) {
curr = sma->sem_base + sop->sem_num;
curr->semval -= sop->sem_op;
curr->sempid >>= 16; /*!!!!!!*/
---------------------------------------------------------------------------

The simplest fix is just to swap the "wait for zero" condition and
PID backup, like this:

curr->sempid = (curr->sempid << 16) | pid;

if (!sem_op && curr->semval)
goto would_block;

Cheers,

Anton Lavrentiev
NCBI/NLM/NIH
Bethesda MD 20894
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/


nt ret;
+
+ current->flags &= ~PF_MEMALLOC;
+ ret = add_to_swap_cache(page, entry);
+ current->flags = flags;
+ return ret;
+}
+
+/*
* The swap-out function returns 1 if it successfully
* scanned all the pages it was asked to (`count').
* It returns zero if it couldn't do anything,
@@ -140,7 +163,7 @@ drop_pte:
* (adding to the page cache will clear the dirty
* and uptodate bits, so we need to do it again)
*/
- switch (add_to_swap_cache(page, entry)) {
+ switch (swap_out_add_to_swap_cache(page, entry)) {
case 0: /* Success */
SetPageUptodate(page);
set_page_dirty(page);
--- 2.5.8-pre3/lib/radix-tree.c~ratcache-pf_memalloc Fri Apr 12 23:40:35 2002
+++ 2.5.8-pre3-akpm/lib/radix-tree.c Fri Apr 12 23:54:49 2002
@@ -49,11 +49,27 @@ struct radix_tree_path {
static kmem_cache_t *radix_tree_node_cachep;
static mempool_t *radix_tree_node_pool;

-#define radix_tree_node_alloc(root) \
- mempool_alloc(radix_tree_node_pool, (root)->gfp_mask)
-#define radix_tree_node_free(node) \
- mempool_free((node), radix_tree_node_pool);
+/*
+ * mempool scribbles on the first eight bytes of the managed
+ * memory. Here we implement a temp workaround for that.
+ */
+#include <linux/list.h>
+static inline struct radix_tree_node *
+radix_tree_node_alloc(struct radix_tree_root *root)
+{
+ struct radix_tree_node *ret;
+
+ ret = mempool_alloc(radix_tree_node_pool, root->gfp_mask);
+ if (ret)
+ memset(ret, 0, sizeof(struct list_head));
+ return ret;
+}

+static inline void
+radix_tree_node_free(struct radix_tree_node *node)
+{
+ mempool_free(node, radix_tree_node_pool);
+}

/*
* Return the maximum key which can be store into a

-
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/