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

Changeset 5d96851 in mainline


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.

Location:
uspace
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/task.c

    r7114d83 r5d96851  
    163163int task_retval(int val)
    164164{
    165         task_id_t id;
    166 
    167         id = task_get_id();
    168         return (int) async_req_3_0(PHONE_NS, NS_RETVAL, LOWER32(id),
    169             UPPER32(id), val);
     165        return (int) async_req_1_0(PHONE_NS, NS_RETVAL, val);
    170166}
    171167
  • uspace/lib/libc/include/ipc/ns.h

    r7114d83 r5d96851  
    4141        NS_PING = IPC_FIRST_USER_METHOD,
    4242        NS_TASK_WAIT,
     43        NS_ID_INTRO,
    4344        NS_RETVAL
    4445} ns_request_t;
  • uspace/srv/loader/main.c

    r7114d83 r5d96851  
    5353#include <ipc/services.h>
    5454#include <ipc/loader.h>
     55#include <ipc/ns.h>
     56#include <macros.h>
    5557#include <loader/pcb.h>
    5658#include <errno.h>
     
    438440{
    439441        ipcarg_t phonead;
    440        
     442        task_id_t id;
     443        int rc;
     444
    441445        connected = false;
    442        
     446
     447        /* Introduce this task to the NS (give it our task ID). */
     448        id = task_get_id();
     449        rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
     450        if (rc != EOK)
     451                return -1;
     452
    443453        /* Set a handler of incomming connections. */
    444454        async_set_client_connection(ldr_connection);
     
    446456        /* Register at naming service. */
    447457        if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
    448                 return -1;
    449        
     458                return -2;
     459
    450460        async_manager();
    451461       
  • uspace/srv/ns/ns.c

    r7114d83 r5d96851  
    134134                        continue;
    135135                case IPC_M_PHONE_HUNGUP:
    136                         retval = EOK;
     136                        retval = ns_task_disconnect(&call);
    137137                        break;
    138138                case IPC_M_CONNECT_TO_ME:
     
    171171                        wait_for_task(id, &call, callid);
    172172                        continue;
     173                case NS_ID_INTRO:
     174                        retval = ns_task_id_intro(&call);
     175                        break;
    173176                case NS_RETVAL:
    174177                        retval = ns_task_retval(&call);
  • 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;
  • uspace/srv/ns/task.h

    r7114d83 r5d96851  
    4343extern void wait_for_task(task_id_t id, ipc_call_t *call, ipc_callid_t callid);
    4444
     45extern int ns_task_id_intro(ipc_call_t *call);
     46extern int ns_task_disconnect(ipc_call_t *call);
    4547extern int ns_task_retval(ipc_call_t *call);
     48
    4649
    4750#endif
Note: See TracChangeset for help on using the changeset viewer.