Diff for /src/sys/kern/lwkt_caps.c between versions 1.1 and 1.2

version 1.1, 2004/01/18 12:29:49 version 1.2, 2004/03/06 22:14:09
Line 60 Line 60
 static int caps_process_msg(caps_kinfo_t caps, caps_kmsg_t msg, struct caps_sys_get_args *uap);  static int caps_process_msg(caps_kinfo_t caps, caps_kmsg_t msg, struct caps_sys_get_args *uap);
 static void caps_free(caps_kinfo_t caps);  static void caps_free(caps_kinfo_t caps);
 static void caps_free_msg(caps_kmsg_t msg);  static void caps_free_msg(caps_kmsg_t msg);
   static int caps_name_check(const char *name, int len);
 static caps_kinfo_t caps_free_msg_mcaps(caps_kmsg_t msg);  static caps_kinfo_t caps_free_msg_mcaps(caps_kmsg_t msg);
 static caps_kinfo_t kern_caps_sys_service(const char *name, uid_t uid,   static caps_kinfo_t kern_caps_sys_service(const char *name, uid_t uid, 
                         gid_t gid, struct ucred *cred,                           gid_t gid, struct ucred *cred, 
Line 71  static caps_kinfo_t kern_caps_sys_client Line 72  static caps_kinfo_t kern_caps_sys_client
 #define CAPS_HMASK      (CAPS_HSIZE - 1)  #define CAPS_HMASK      (CAPS_HSIZE - 1)
   
 static caps_kinfo_t     caps_hash_ary[CAPS_HSIZE];  static caps_kinfo_t     caps_hash_ary[CAPS_HSIZE];
   static int caps_waitsvc;
   
 MALLOC_DEFINE(M_CAPS, "caps", "caps IPC messaging");  MALLOC_DEFINE(M_CAPS, "caps", "caps IPC messaging");
   
Line 135  caps_find(const char *name, int len, uid Line 137  caps_find(const char *name, int len, uid
   
 static  static
 caps_kinfo_t  caps_kinfo_t
caps_find_id(int id)caps_find_id(thread_t td, int id)
 {  {
    thread_t td = curthread;  
    caps_kinfo_t caps;     caps_kinfo_t caps;
   
    for (caps = td->td_caps; caps; caps = caps->ci_tdnext) {     for (caps = td->td_caps; caps; caps = caps->ci_tdnext) {
Line 151  caps_find_id(int id) Line 152  caps_find_id(int id)
   
 static  static
 caps_kinfo_t  caps_kinfo_t
caps_alloc(const char *name, int len, uid_t uid, gid_t gid, caps_alloc(thread_t td, const char *name, int len, uid_t uid, gid_t gid, 
             int flags, caps_type_t type)              int flags, caps_type_t type)
 {  {
     struct caps_kinfo **chash;      struct caps_kinfo **chash;
     thread_t td = curthread;  
     caps_kinfo_t caps;      caps_kinfo_t caps;
     caps_kinfo_t ctmp;      caps_kinfo_t ctmp;
   
Line 183  caps_alloc(const char *name, int len, ui Line 183  caps_alloc(const char *name, int len, ui
              * It is virtually impossible for this case to occur.               * It is virtually impossible for this case to occur.
              */               */
             caps->ci_id = 1;              caps->ci_id = 1;
            while ((ctmp = caps_find_id(caps->ci_id)) != NULL) {            while ((ctmp = caps_find_id(td, caps->ci_id)) != NULL) {
                 caps_drop(ctmp);                  caps_drop(ctmp);
                 ++caps->ci_id;                  ++caps->ci_id;
             }              }
Line 325  caps_free_msg(caps_kmsg_t msg) Line 325  caps_free_msg(caps_kmsg_t msg)
 }  }
   
 /*  /*
    * Validate the service name
    */
   static int
   caps_name_check(const char *name, int len)
   {
       int i;
       char c;
   
       for (i = len - 1; i >= 0; --i) {
           c = name[i];
           if (c >= '0' && c <= '9')
               continue;
           if (c >= 'a' && c <= 'z')
               continue;
           if (c >= 'A' && c <= 'Z')
               continue;
           if (c == '_' || c == '.')
               continue;
           return(EINVAL);
       }
       return(0);
   }
   
   /*
  * caps_term()   * caps_term()
  *   *
  * Terminate portions of a caps info structure.  This is used to close   * Terminate portions of a caps info structure.  This is used to close
Line 479  caps_free(caps_kinfo_t caps) Line 503  caps_free(caps_kinfo_t caps)
  *                      PROCESS SUPPORT FUNCTIONS                       *   *                      PROCESS SUPPORT FUNCTIONS                       *
  ************************************************************************/   ************************************************************************/
   
   /*
    * Create dummy entries in p2 so we can return the appropriate
    * error code.  Robust userland code will check the error for a
    * forked condition and reforge the connection.
    */
 void  void
caps_fork(struct proc *p1, struct proc *p2)caps_fork(struct proc *p1, struct proc *p2, int flags)
 {  {
    /* create dummy caps entries that fail?  Or dup client entries? XXX */    caps_kinfo_t caps1;
     caps_kinfo_t caps2;
     thread_t td1;
     thread_t td2;
 
     td1 = p1->p_thread;
     td2 = p2->p_thread;
 
     /*
      * Create dummy entries with the same id's as the originals.  Note
      * that service entries are not re-added to the hash table. The
      * dummy entries return an ENOTCONN error allowing userland code to
      * detect that a fork occured.  Userland must reconnect to the service.
      */
     for (caps1 = td1->td_caps; caps1; caps1 = caps1->ci_tdnext) {
         if (caps1->ci_flags & CAPF_NOFORK)
                 continue;
         caps2 = caps_alloc(td2,
                         caps1->ci_name, caps1->ci_namelen,
                         caps1->ci_uid, caps1->ci_gid,
                         caps1->ci_flags & CAPF_UFLAGS, CAPT_FORKED);
         caps2->ci_id = caps1->ci_id;
     }
 
     /*
      * Reverse the list order to maintain highest-id-first
      */
     caps2 = td2->td_caps;
     td2->td_caps = NULL;
     while (caps2) {
         caps1 = caps2->ci_tdnext;
         caps2->ci_tdnext = td2->td_caps;
         td2->td_caps = caps2;
         caps2 = caps1;
     }
 }  }
   
 void  void
Line 525  caps_sys_service(struct caps_sys_service Line 588  caps_sys_service(struct caps_sys_service
         return(error);          return(error);
     if (--len <= 0)      if (--len <= 0)
         return(EINVAL);          return(EINVAL);
       if ((error = caps_name_check(name, len)) != 0)
           return(error);
   
     caps = kern_caps_sys_service(name, uap->uid, uap->gid, cred,      caps = kern_caps_sys_service(name, uap->uid, uap->gid, cred,
                                 uap->flags & CAPF_UFLAGS, &error);                                  uap->flags & CAPF_UFLAGS, &error);
Line 557  caps_sys_client(struct caps_sys_client_a Line 622  caps_sys_client(struct caps_sys_client_a
         return(error);          return(error);
     if (--len <= 0)      if (--len <= 0)
         return(EINVAL);          return(EINVAL);
       if ((error = caps_name_check(name, len)) != 0)
           return(error);
   
     caps = kern_caps_sys_client(name, uap->uid, uap->gid, cred,      caps = kern_caps_sys_client(name, uap->uid, uap->gid, cred,
                                 uap->flags & CAPF_UFLAGS, &error);                                  uap->flags & CAPF_UFLAGS, &error);
Line 570  caps_sys_close(struct caps_sys_close_arg Line 637  caps_sys_close(struct caps_sys_close_arg
 {  {
     caps_kinfo_t caps;      caps_kinfo_t caps;
   
    if ((caps = caps_find_id(uap->portid)) == NULL)    if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
         return(EINVAL);          return(EINVAL);
     caps_term(caps, CAPKF_TDLIST|CAPKF_HLIST|CAPKF_FLUSH|CAPKF_RCAPS, NULL);      caps_term(caps, CAPKF_TDLIST|CAPKF_HLIST|CAPKF_FLUSH|CAPKF_RCAPS, NULL);
     caps_drop(caps);      caps_drop(caps);
     return(0);      return(0);
 }  }
   
   int
   caps_sys_setgen(struct caps_sys_setgen_args *uap)
   {
       caps_kinfo_t caps;
   
       if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
           return(EINVAL);
       if (caps->ci_type == CAPT_FORKED)
           return(ENOTCONN);
       caps->ci_gen = uap->gen;
       return(0);
   }
   
   int
   caps_sys_getgen(struct caps_sys_getgen_args *uap)
   {
       caps_kinfo_t caps;
   
       if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
           return(EINVAL);
       if (caps->ci_type == CAPT_FORKED)
           return(ENOTCONN);
       if (caps->ci_rcaps == NULL)
           return(EINVAL);
       uap->sysmsg_result64 = caps->ci_rcaps->ci_gen;
       return(0);
   }
   
 /*  /*
  * caps_sys_put(portid, msg, msgsize)   * caps_sys_put(portid, msg, msgsize)
  *   *
Line 589  caps_sys_put(struct caps_sys_put_args *u Line 684  caps_sys_put(struct caps_sys_put_args *u
     caps_kinfo_t caps;      caps_kinfo_t caps;
     caps_kmsg_t msg;      caps_kmsg_t msg;
     struct proc *p = curproc;      struct proc *p = curproc;
       int error;
   
     if (uap->msgsize < 0)      if (uap->msgsize < 0)
         return(EINVAL);          return(EINVAL);
    if ((caps = caps_find_id(uap->portid)) == NULL)    if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
         return(EINVAL);          return(EINVAL);
       if (caps->ci_type == CAPT_FORKED)
           return(ENOTCONN);
     if (caps->ci_rcaps == NULL) {      if (caps->ci_rcaps == NULL) {
         caps_drop(caps);          caps_drop(caps);
         return(EINVAL);          return(EINVAL);
Line 614  caps_sys_put(struct caps_sys_put_args *u Line 712  caps_sys_put(struct caps_sys_put_args *u
     uap->sysmsg_offset = msg->km_msgid.c_id;      uap->sysmsg_offset = msg->km_msgid.c_id;
   
     /*      /*
     * If the remote end is closed reply the message immediately, otherwise     * If the remote end is closed return ENOTCONN immediately, otherwise
     * send it to the remote end.  Disposal XXX     * send it to the remote end.
      *       *
      * Note: since this is a new message, caps_load_ccr() returns a remote       * Note: since this is a new message, caps_load_ccr() returns a remote
      * caps of NULL.       * caps of NULL.
      */       */
       error = 0;
     if (caps->ci_rcaps->ci_flags & CAPKF_CLOSED) {      if (caps->ci_rcaps->ci_flags & CAPKF_CLOSED) {
           error = ENOTCONN;
           caps_free_msg(msg);
   #if 0
         caps_load_ccr(caps, msg, p, NULL, 0);   /* returns NULL */          caps_load_ccr(caps, msg, p, NULL, 0);   /* returns NULL */
         caps_hold(caps);          caps_hold(caps);
         caps_put_msg(caps, msg, CAPMS_REPLY);   /* drops caps */          caps_put_msg(caps, msg, CAPMS_REPLY);   /* drops caps */
   #endif
     } else {      } else {
         caps_load_ccr(caps, msg, p, uap->msg, uap->msgsize); /* returns NULL */          caps_load_ccr(caps, msg, p, uap->msg, uap->msgsize); /* returns NULL */
         caps_hold(caps->ci_rcaps);                        /* need ref */          caps_hold(caps->ci_rcaps);                        /* need ref */
Line 631  caps_sys_put(struct caps_sys_put_args *u Line 734  caps_sys_put(struct caps_sys_put_args *u
         caps_put_msg(caps->ci_rcaps, msg, CAPMS_REQUEST); /* drops rcaps */          caps_put_msg(caps->ci_rcaps, msg, CAPMS_REQUEST); /* drops rcaps */
     }      }
     caps_drop(caps);      caps_drop(caps);
    return(0);    return(error);
 }  }
   
 /*  /*
Line 650  caps_sys_reply(struct caps_sys_reply_arg Line 753  caps_sys_reply(struct caps_sys_reply_arg
   
     if (uap->msgsize < 0)      if (uap->msgsize < 0)
         return(EINVAL);          return(EINVAL);
    if ((caps = caps_find_id(uap->portid)) == NULL)    if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
         return(EINVAL);          return(EINVAL);
       if (caps->ci_type == CAPT_FORKED)
           return(ENOTCONN);
   
     /*      /*
      * Can't find message to reply to       * Can't find message to reply to
Line 709  caps_sys_get(struct caps_sys_get_args *u Line 814  caps_sys_get(struct caps_sys_get_args *u
   
     if (uap->maxsize < 0)      if (uap->maxsize < 0)
         return(EINVAL);          return(EINVAL);
    if ((caps = caps_find_id(uap->portid)) == NULL)    if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
         return(EINVAL);          return(EINVAL);
       if (caps->ci_type == CAPT_FORKED)
           return(ENOTCONN);
     if ((msg = TAILQ_FIRST(&caps->ci_msgpendq)) == NULL) {      if ((msg = TAILQ_FIRST(&caps->ci_msgpendq)) == NULL) {
         caps_drop(caps);          caps_drop(caps);
         return(EWOULDBLOCK);          return(EWOULDBLOCK);
Line 741  caps_sys_wait(struct caps_sys_wait_args Line 848  caps_sys_wait(struct caps_sys_wait_args
   
     if (uap->maxsize < 0)      if (uap->maxsize < 0)
         return(EINVAL);          return(EINVAL);
    if ((caps = caps_find_id(uap->portid)) == NULL)    if ((caps = caps_find_id(curthread, uap->portid)) == NULL)
         return(EINVAL);          return(EINVAL);
       if (caps->ci_type == CAPT_FORKED)
           return(ENOTCONN);
     while ((msg = TAILQ_FIRST(&caps->ci_msgpendq)) == NULL) {      while ((msg = TAILQ_FIRST(&caps->ci_msgpendq)) == NULL) {
         if ((error = tsleep(caps, PCATCH, "caps", 0)) != 0) {          if ((error = tsleep(caps, PCATCH, "caps", 0)) != 0) {
             caps_drop(caps);              caps_drop(caps);
Line 874  kern_caps_sys_service(const char *name, Line 983  kern_caps_sys_service(const char *name,
     /*      /*
      * Create the service       * Create the service
      */       */
    caps = caps_alloc(name, len, uid, gid, flags & CAPF_UFLAGS, CAPT_SERVICE);    caps = caps_alloc(curthread, name, len, 
                         uid, gid, flags & CAPF_UFLAGS, CAPT_SERVICE);
     wakeup(&caps_waitsvc);
     return(caps);      return(caps);
 }  }
   
Line 891  kern_caps_sys_client(const char *name, u Line 1002  kern_caps_sys_client(const char *name, u
     /*      /*
      * Locate the CAPS service (rcaps ref is for caps->ci_rcaps)       * Locate the CAPS service (rcaps ref is for caps->ci_rcaps)
      */       */
   again:
     if ((rcaps = caps_find(name, len, uid, gid)) == NULL) {      if ((rcaps = caps_find(name, len, uid, gid)) == NULL) {
        *error = ENOENT;        if (flags & CAPF_WAITSVC) {
             char cbuf[32];
             snprintf(cbuf, sizeof(cbuf), "C%s", name);
             *error = tsleep(&caps_waitsvc, PCATCH, cbuf, 0);
             if (*error == 0)
                 goto again;
         } else {
             *error = ENOENT;
         }
         return(NULL);          return(NULL);
     }      }
   
Line 923  kern_caps_sys_client(const char *name, u Line 1043  kern_caps_sys_client(const char *name, u
     /*      /*
      * Allocate the client side and connect to the server       * Allocate the client side and connect to the server
      */       */
    caps = caps_alloc(name, len, uid, gid, flags & CAPF_UFLAGS, CAPT_CLIENT);    caps = caps_alloc(curthread, name, len, 
                         uid, gid, flags & CAPF_UFLAGS, CAPT_CLIENT);
     caps->ci_rcaps = rcaps;      caps->ci_rcaps = rcaps;
     caps->ci_flags |= CAPKF_RCAPS;      caps->ci_flags |= CAPKF_RCAPS;
     return(caps);      return(caps);

Removed from v.1.1  
changed lines
  Added in v.1.2