Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 5d96851 in mainline for uspace/srv/ns/task.c


Ignore:
Timestamp:
2009-07-06T19:17:49Z (12 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master
Children:
0315679
Parents:
7114d83
Message:

Pass task ID to NS from loader. This prevents ID spoofing by user apps.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/ns/task.c

    r7114d83 r5d96851  
    11/*
    22 * Copyright (c) 2009 Martin Decky
     3 * Copyright (c) 2009 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    4243
    4344#define TASK_HASH_TABLE_CHAINS  256
     45#define P2I_HASH_TABLE_CHAINS  256
     46
     47static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id);
    4448
    4549/* TODO:
    4650 *
    4751 * The current implementation of waiting on a task is not perfect. If somebody
    48  * wants to wait on a task which has already finished before the NS asked
    49  * the kernel to receive notifications, it would block indefinitively.
    50  *
    51  * A solution to this is to fail immediately on a task for which no creation
    52  * notification was received yet. However, there is a danger of a race condition
    53  * in this solution -- the caller has to make sure that it is not trying to wait
     52 * The caller has to make sure that it is not trying to wait
    5453 * before the NS has a change to receive the task creation notification. This
    5554 * can be assured by waiting for this event in task_spawn().
     
    8584 *
    8685 * @param key  Array of keys.
    87  * @param keys Must be lesser or equal to 2.
     86 * @param keys Must be less than or equal to 2.
    8887 * @param item Pointer to a hash table item.
    8988 *
     
    127126static hash_table_t task_hash_table;
    128127
     128typedef struct {
     129        link_t link;
     130        ipcarg_t phash;    /**< Task ID. */
     131        task_id_t id;    /**< Task ID. */
     132} p2i_entry_t;
     133
     134/** Compute hash index into task hash table.
     135 *
     136 * @param key Array of keys.
     137 * @return Hash index corresponding to key[0].
     138 *
     139 */
     140static hash_index_t p2i_hash(unsigned long *key)
     141{
     142        assert(key);
     143        return (*key % TASK_HASH_TABLE_CHAINS);
     144}
     145
     146/** Compare a key with hashed item.
     147 *
     148 * @param key  Array of keys.
     149 * @param keys Must be less than or equal to 1.
     150 * @param item Pointer to a hash table item.
     151 *
     152 * @return Non-zero if the key matches the item, zero otherwise.
     153 *
     154 */
     155static int p2i_compare(unsigned long key[], hash_count_t keys, link_t *item)
     156{
     157        assert(key);
     158        assert(keys == 1);
     159        assert(item);
     160
     161        p2i_entry_t *e = hash_table_get_instance(item, p2i_entry_t, link);
     162
     163        return (key[0] == e->phash);
     164}
     165
     166/** Perform actions after removal of item from the hash table.
     167 *
     168 * @param item Item that was removed from the hash table.
     169 *
     170 */
     171static void p2i_remove(link_t *item)
     172{
     173        assert(item);
     174        free(hash_table_get_instance(item, p2i_entry_t, link));
     175}
     176
     177/** Operations for task hash table. */
     178static hash_table_operations_t p2i_ops = {
     179        .hash = p2i_hash,
     180        .compare = p2i_compare,
     181        .remove_callback = p2i_remove
     182};
     183
     184/** Map phone hash to task ID */
     185static hash_table_t phone_to_id;
     186
    129187/** Pending task wait structure. */
    130188typedef struct {
     
    140198        if (!hash_table_create(&task_hash_table, TASK_HASH_TABLE_CHAINS,
    141199            2, &task_hash_table_ops)) {
     200                printf(NAME ": No memory available for tasks\n");
     201                return ENOMEM;
     202        }
     203
     204        if (!hash_table_create(&phone_to_id, P2I_HASH_TABLE_CHAINS,
     205            1, &p2i_ops)) {
    142206                printf(NAME ": No memory available for tasks\n");
    143207                return ENOMEM;
     
    239303                UPPER32(id)
    240304        };
    241        
     305
    242306        link_t *link = hash_table_find(&task_hash_table, keys);
    243307        hashed_task_t *ht = (link != NULL) ?
    244308            hash_table_get_instance(link, hashed_task_t, link) : NULL;
    245        
    246         if ((ht == NULL) || (!ht->destroyed)) {
     309
     310        if (ht == NULL) {
     311                retval = ENOENT;
     312                goto out;
     313        }
     314
     315        if (!ht->destroyed) {
    247316                /* Add to pending list */
    248317                pending_wait_t *pr =
     
    267336}
    268337
     338int ns_task_id_intro(ipc_call_t *call)
     339{
     340        task_id_t id;
     341        unsigned long keys[1];
     342        link_t *link;
     343        p2i_entry_t *e;
     344
     345        id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
     346
     347        keys[0] = call->in_phone_hash;
     348
     349        link = hash_table_find(&phone_to_id, keys);
     350        if (link != NULL)
     351                return EEXISTS;
     352
     353        e = (p2i_entry_t *) malloc(sizeof(p2i_entry_t));
     354        if (e == NULL)
     355                return ENOMEM;
     356
     357        link_initialize(&e->link);
     358        e->phash = call->in_phone_hash;
     359        e->id = id;
     360        hash_table_insert(&phone_to_id, keys, &e->link);
     361
     362        return EOK;
     363}
     364
    269365int ns_task_retval(ipc_call_t *call)
    270366{
    271367        task_id_t id;
    272368        unsigned long keys[2];
    273 
    274         id = MERGE_LOUP32(IPC_GET_ARG1(*call), IPC_GET_ARG2(*call));
     369        int rc;
     370
     371        rc = get_id_by_phone(call->in_phone_hash, &id);
     372        if (rc != EOK)
     373                return rc;
    275374
    276375        keys[0] = LOWER32(id);
     
    284383                return EINVAL;
    285384
    286         ht->retval = IPC_GET_ARG3(*call);
     385        ht->retval = IPC_GET_ARG1(*call);
     386
     387        return EOK;
     388}
     389
     390int ns_task_disconnect(ipc_call_t *call)
     391{
     392        unsigned long keys[1];
     393
     394        keys[0] = call->in_phone_hash;
     395        hash_table_remove(&phone_to_id, keys, 1);
     396       
     397        return EOK;
     398}
     399
     400static int get_id_by_phone(ipcarg_t phone_hash, task_id_t *id)
     401{
     402        unsigned long keys[1];
     403        link_t *link;
     404        p2i_entry_t *e;
     405
     406        keys[0] = phone_hash;
     407        link = hash_table_find(&phone_to_id, keys);
     408        if (link == NULL)
     409                return ENOENT;
     410
     411        e = hash_table_get_instance(link, p2i_entry_t, link);
     412        *id = e->id;
    287413
    288414        return EOK;
Note: See TracChangeset for help on using the changeset viewer.