~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to services/plugins/dndcp/dnd/dndMsg.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2007 VMware, Inc. All rights reserved.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License as published
 
6
 * by the Free Software Foundation version 2.1 and no later version.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
10
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the Lesser GNU General Public
 
11
 * License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
 
16
 *
 
17
 *********************************************************/
 
18
 
 
19
/*
 
20
 * dndMsg.c --
 
21
 *
 
22
 *      DnDMsg represents an rpc message which is sent across the
 
23
 *      wire. Any args that it holds will be written out exactly as stored.
 
24
 *
 
25
 *      To protect itself there are many checks to ensure the data which is
 
26
 *      serialized and unserialized is sane. Defines and asserts are used to
 
27
 *      ensure the message stays under these limits when serializing out and
 
28
 *      checks are enforced to ensure that the data to be unserialized remains
 
29
 *      under these limits.
 
30
 */
 
31
 
 
32
#include <stdlib.h>
 
33
#include <string.h>
 
34
#include "vm_assert.h"
 
35
 
 
36
#include "dndMsg.h"
 
37
#include "dndInt.h"
 
38
 
 
39
#define LOGLEVEL_MODULE dnd
 
40
#include "loglevel_user.h"
 
41
 
 
42
 
 
43
/*
 
44
 *----------------------------------------------------------------------------
 
45
 *
 
46
 * DnDMsg_Init --
 
47
 *
 
48
 *      DnDMsg constructor.
 
49
 *
 
50
 * Results:
 
51
 *      None.
 
52
 *
 
53
 * Side effects:
 
54
 *      None
 
55
 *
 
56
 *----------------------------------------------------------------------------
 
57
 */
 
58
 
 
59
void
 
60
DnDMsg_Init(DnDMsg *msg)   // IN/OUT: the message
 
61
{
 
62
   ASSERT(msg);
 
63
 
 
64
   msg->ver = 3;
 
65
   msg->cmd = 0;
 
66
   msg->nargs = 0;
 
67
   DynBufArray_Init(&msg->args, 0);
 
68
   msg->expectedArgsSz = 0;
 
69
}
 
70
 
 
71
 
 
72
/*
 
73
 *----------------------------------------------------------------------------
 
74
 *
 
75
 * DnDMsg_Destroy --
 
76
 *
 
77
 *      Destroys a message by clearing any of the data that is contained in it.
 
78
 *
 
79
 * Results:
 
80
 *      None
 
81
 *
 
82
 * Side effects:
 
83
 *      Frees the arguments' memory.
 
84
 *
 
85
 *----------------------------------------------------------------------------
 
86
 */
 
87
 
 
88
void
 
89
DnDMsg_Destroy(DnDMsg *msg)  // IN/OUT: the message
 
90
{
 
91
   uint32 i;
 
92
   uint32 count;
 
93
 
 
94
   ASSERT(msg);
 
95
 
 
96
   count = DynArray_Count(&msg->args);
 
97
 
 
98
   msg->ver = 0;
 
99
   msg->cmd = 0;
 
100
   msg->nargs = 0;
 
101
   msg->expectedArgsSz = 0;
 
102
 
 
103
   for (i = 0; i < count; ++i) {
 
104
      DynBuf *b = DynArray_AddressOf(&msg->args, i);
 
105
      DynBuf_Destroy(b);
 
106
   }
 
107
   DynArray_SetCount(&msg->args, 0);
 
108
   DynBufArray_Destroy(&msg->args);
 
109
}
 
110
 
 
111
 
 
112
/*
 
113
 *----------------------------------------------------------------------------
 
114
 *
 
115
 * DnDMsg_Cmd --
 
116
 *
 
117
 *      Gets the dnd/copy paste command from the header.
 
118
 *
 
119
 * Results:
 
120
 *      An uint32 representing the command.
 
121
 *
 
122
 * Side effects:
 
123
 *      None.
 
124
 *
 
125
 *----------------------------------------------------------------------------
 
126
 */
 
127
 
 
128
uint32
 
129
DnDMsg_GetCmd(DnDMsg *msg)      // IN/OUT: the message
 
130
{
 
131
   ASSERT(msg);
 
132
 
 
133
   return msg->cmd;
 
134
}
 
135
 
 
136
 
 
137
/*
 
138
 *----------------------------------------------------------------------------
 
139
 *
 
140
 * DnDMsg_SetCmd --
 
141
 *
 
142
 *      Sets the command for the message.
 
143
 *
 
144
 * Results:
 
145
 *      None.
 
146
 *
 
147
 * Side effects:
 
148
 *      None.
 
149
 *
 
150
 *----------------------------------------------------------------------------
 
151
 */
 
152
 
 
153
void
 
154
DnDMsg_SetCmd(DnDMsg *msg,      // IN/OUT: the message
 
155
              uint32 cmd)       // IN: the command
 
156
{
 
157
   ASSERT(msg);
 
158
   ASSERT((DND_INVALID < cmd && cmd < DND_MAX) ||
 
159
          (CP_INVALID < cmd && cmd < CP_MAX));
 
160
 
 
161
   msg->cmd = cmd;
 
162
}
 
163
 
 
164
 
 
165
/*
 
166
 *----------------------------------------------------------------------------
 
167
 *
 
168
 * DnDMsg_NumArgs --
 
169
 *
 
170
 *      Determines the number of arguments currently in the DnDMsg.
 
171
 *
 
172
 * Results:
 
173
 *      The number of arguments.
 
174
 *
 
175
 * Side effects:
 
176
 *      None.
 
177
 *
 
178
 *----------------------------------------------------------------------------
 
179
 */
 
180
 
 
181
uint32
 
182
DnDMsg_NumArgs(DnDMsg *msg)     // IN/OUT: the message
 
183
{
 
184
   ASSERT(msg);
 
185
 
 
186
   return DynBufArray_Count(&msg->args);
 
187
}
 
188
 
 
189
 
 
190
/*
 
191
 *----------------------------------------------------------------------------
 
192
 *
 
193
 * DnDMsg_GetArg --
 
194
 *
 
195
 *      Gets an argument stored in DnDMsg.
 
196
 *
 
197
 * Results:
 
198
 *      Null if the argument is out of bounds, otherwise a pointer to a dynbuf
 
199
 *      containing the argument.
 
200
 *       This dynbuf is still
 
201
 *      managed by the DnDMsg and should NOT be destroyed.
 
202
 *
 
203
 * Side effects:
 
204
 *      None.
 
205
 *
 
206
 *----------------------------------------------------------------------------
 
207
 */
 
208
 
 
209
DynBuf *
 
210
DnDMsg_GetArg(DnDMsg *msg,      // IN/OUT: the message
 
211
              uint32 idx)       // IN: the argument to return
 
212
{
 
213
   ASSERT(msg);
 
214
   ASSERT(0 <= idx && idx < DynBufArray_Count(&msg->args));
 
215
 
 
216
   return DynArray_AddressOf(&msg->args, idx);
 
217
}
 
218
 
 
219
 
 
220
/*
 
221
 *----------------------------------------------------------------------------
 
222
 *
 
223
 * DnDMsg_AppendArg --
 
224
 *
 
225
 *      Adds the data to the end of the argument list in the message. It will
 
226
 *      create a copy of the data to be mananged by DnDMsg until the message is
 
227
 *      destroyed.
 
228
 *
 
229
 * Results:
 
230
 *      TRUE on success, FALSE on failure.
 
231
 *
 
232
 * Side effects:
 
233
 *      Increases the internal arg size counter.
 
234
 *
 
235
 *----------------------------------------------------------------------------
 
236
 */
 
237
 
 
238
Bool
 
239
DnDMsg_AppendArg(DnDMsg *msg,   // IN/OUT: the message
 
240
                 void *buf,     // IN: the input buffer
 
241
                 size_t len)    // IN: the length of the input buffer
 
242
{
 
243
   DynBuf clonebuf;
 
244
 
 
245
   ASSERT(msg);
 
246
   ASSERT(buf);
 
247
 
 
248
   if (DynBufArray_Count(&msg->args) >= DNDMSG_MAX_ARGS) {
 
249
      return FALSE;
 
250
   }
 
251
 
 
252
   DynBuf_Init(&clonebuf);
 
253
   if (!DynBuf_Append(&clonebuf, buf, len)) {
 
254
      goto err;
 
255
   }
 
256
 
 
257
   /* The dynbufarray now owns the clonebuf data. */
 
258
   if (!DynBufArray_Push(&msg->args, clonebuf)) {
 
259
      goto err;
 
260
   }
 
261
   return TRUE;
 
262
 
 
263
err:
 
264
   DynBuf_Destroy(&clonebuf);
 
265
   return FALSE;
 
266
}
 
267
 
 
268
 
 
269
/*
 
270
 *----------------------------------------------------------------------------
 
271
 *
 
272
 * DnDMsg_Serialize --
 
273
 *
 
274
 *      Serialize the contents of the DnDMsg out to the provided dynbuf. It
 
275
 *      will ASSERT if any invariants are broken.
 
276
 *
 
277
 * Results:
 
278
 *      TRUE on success.
 
279
 *      FALSE on failure.
 
280
 *
 
281
 * Side effects:
 
282
 *      None.
 
283
 *
 
284
 *----------------------------------------------------------------------------
 
285
 */
 
286
 
 
287
Bool
 
288
DnDMsg_Serialize(DnDMsg *msg,   // IN/OUT: the message
 
289
                 DynBuf* buf)   // OUT: the output buffer
 
290
{
 
291
   DynBuf *curArg;
 
292
   uint32 nargs;
 
293
   uint32 i;
 
294
   uint32 serializeArgsSz = 0;
 
295
 
 
296
   ASSERT(msg);
 
297
   ASSERT(buf);
 
298
   ASSERT((DND_INVALID < msg->cmd && msg->cmd < DND_MAX) ||
 
299
          (CP_INVALID < msg->cmd && msg->cmd < CP_MAX));
 
300
 
 
301
   nargs = DynBufArray_Count(&msg->args);
 
302
 
 
303
   for (i = 0; i < nargs; ++i) {
 
304
      DynBuf *b = DynArray_AddressOf(&msg->args, i);
 
305
      serializeArgsSz += sizeof(uint32) + DynBuf_GetSize(b);
 
306
   }
 
307
 
 
308
   if (DynBuf_Append(buf, &msg->ver, sizeof msg->ver) &&
 
309
       DynBuf_Append(buf, &msg->cmd, sizeof msg->cmd) &&
 
310
       DynBuf_Append(buf, &nargs, sizeof nargs) &&
 
311
       DynBuf_Append(buf, &serializeArgsSz, sizeof serializeArgsSz)) {
 
312
      int i;
 
313
      uint32 curArgsSz;
 
314
 
 
315
      for (i = 0; i < nargs; i++) {
 
316
         curArg = DynBufArray_AddressOf(&msg->args, i);
 
317
         curArgsSz = DynBuf_GetSize(curArg);
 
318
 
 
319
         if (!DynBuf_Append(buf, &curArgsSz, sizeof curArgsSz) ||
 
320
             !DynBuf_Append(buf, DynBuf_Get(curArg), curArgsSz)) {
 
321
            return FALSE;
 
322
         }
 
323
      }
 
324
   } else {
 
325
      return FALSE;
 
326
   }
 
327
 
 
328
   return TRUE;
 
329
}
 
330
 
 
331
 
 
332
/*
 
333
 *----------------------------------------------------------------------------
 
334
 *
 
335
 * DnDMsg_UnserializeHeader --
 
336
 *
 
337
 *      Read the header from the buffer into a DnDMsg. Any contents in the
 
338
 *      DnDMsg will be destroyed. This allows you to retrieve header
 
339
 *      information. These functions are specified in the dndMsg.h. Most
 
340
 *      notably, you can retrieve the size of the arguments so that you can
 
341
 *      pass a properly sized buffer to DnDMsg_UnserializeArgs.
 
342
 *
 
343
 *      This is the one of the two places that nargs is set. The other is
 
344
 *      implicitly set by DnDMsg_AppendArg with the push and only ever
 
345
 *      realized through the DnDMsg_Serialize function. expectedArgsSz,
 
346
 *      curArgSz follows the same idea.
 
347
 *
 
348
 * Results:
 
349
 *      DNDMSG_SUCCESS on success.
 
350
 *      DNDMSG_INPUT_TOO_SMALL when provided buffer is too small.
 
351
 *      DNDMSG_INPUT_ERR when the provided buffer is inconsistant.
 
352
 *      DNDMSG_NOMEM when we run out of memory.
 
353
 *      DNDMSG_ERR on any other error.
 
354
 *
 
355
 * Side effects:
 
356
 *      On success the msg's header will be filled. On failure the msg will be
 
357
 *      destroyed.
 
358
 *
 
359
 *----------------------------------------------------------------------------
 
360
 */
 
361
 
 
362
DnDMsgErr
 
363
DnDMsg_UnserializeHeader(DnDMsg *msg,   // IN/OUT: the message
 
364
                         void *buf,     // IN: the input buffer
 
365
                         size_t len)    // IN: the buffer length
 
366
{
 
367
   BufRead r;
 
368
 
 
369
   ASSERT(msg);
 
370
   ASSERT(buf);
 
371
 
 
372
   r.pos = buf;
 
373
   r.unreadLen = len;
 
374
 
 
375
   if (len < DNDMSG_HEADERSIZE_V3) {
 
376
      return DNDMSG_INPUT_TOO_SMALL;
 
377
   }
 
378
 
 
379
   /* Read buffer into msg. */
 
380
   if (DnDReadBuffer(&r, &msg->ver, sizeof msg->ver) &&
 
381
       DnDReadBuffer(&r, &msg->cmd, sizeof msg->cmd) &&
 
382
       DnDReadBuffer(&r, &msg->nargs, sizeof msg->nargs) &&
 
383
       DnDReadBuffer(&r, &msg->expectedArgsSz, sizeof msg->expectedArgsSz)) {
 
384
      /* Sanity checks. */
 
385
      if (msg->expectedArgsSz < DNDMSG_MAX_ARGSZ &&
 
386
          (msg->cmd < DND_MAX || msg->cmd < CP_MAX) &&
 
387
          0 < msg->cmd &&
 
388
          msg->ver >= 3 &&
 
389
          msg->nargs < DNDMSG_MAX_ARGS) {
 
390
         return DNDMSG_SUCCESS;
 
391
      } else {
 
392
         return DNDMSG_INPUT_ERR;
 
393
      }
 
394
   } else {
 
395
      return DNDMSG_INPUT_TOO_SMALL;
 
396
   }
 
397
}
 
398
 
 
399
 
 
400
/*
 
401
 *----------------------------------------------------------------------------
 
402
 *
 
403
 * DnDMsg_UnserializeArgs --
 
404
 *
 
405
 *      Unserialize the arguments of the message provided by the buffer.
 
406
 *      Each argument is a uint32 of the size followed by the buffer. On
 
407
 *      failure the message will revert to the state which was passed into the
 
408
 *      function.
 
409
 *
 
410
 * Results:
 
411
 *      DNDMSG_SUCCESS on success.
 
412
 *      DNDMSG_INPUT_TOO_SMALL when provided buffer is too small.
 
413
 *      DNDMSG_INPUT_ERR when the provided buffer is inconsistant.
 
414
 *      DNDMSG_NOMEM when we run out of memory.
 
415
 *      DNDMSG_ERR on any other error.
 
416
 *
 
417
 * Side effects:
 
418
 *      On success, arguments found in buf are unserialized into msg.
 
419
 *
 
420
 *----------------------------------------------------------------------------
 
421
 */
 
422
 
 
423
DnDMsgErr
 
424
DnDMsg_UnserializeArgs(DnDMsg *msg,     // IN/OUT: the message
 
425
                       void *buf,       // IN: input buffer
 
426
                       size_t len)      // IN: buffer length
 
427
{
 
428
   uint32 i;
 
429
   uint32 count;
 
430
   BufRead r;
 
431
   uint32 readArgsSz = 0;
 
432
 
 
433
   void *data = NULL;
 
434
   DnDMsgErr ret = DNDMSG_SUCCESS;
 
435
 
 
436
   ASSERT(msg);
 
437
   ASSERT(DynBufArray_Count(&msg->args) == 0);
 
438
   ASSERT(buf);
 
439
 
 
440
   r.pos = buf;
 
441
   r.unreadLen = len;
 
442
 
 
443
   if (len < msg->expectedArgsSz) {
 
444
      return DNDMSG_INPUT_TOO_SMALL;
 
445
   }
 
446
 
 
447
   for (i = 0; i < msg->nargs; ++i) {
 
448
      uint32 argSz;
 
449
      if (!DnDReadBuffer(&r, &argSz, sizeof argSz)) {
 
450
         ret = DNDMSG_INPUT_TOO_SMALL;
 
451
         goto err;
 
452
      }
 
453
 
 
454
      if (argSz > DNDMSG_MAX_ARGSZ ||
 
455
          readArgsSz + sizeof (uint32) + argSz > msg->expectedArgsSz) {
 
456
         ret = DNDMSG_INPUT_ERR;
 
457
         goto err;
 
458
      }
 
459
 
 
460
      data = malloc(argSz);
 
461
      if (!data) {
 
462
         ret = DNDMSG_NOMEM;
 
463
         goto err;
 
464
      }
 
465
 
 
466
      if (!DnDReadBuffer(&r, data, argSz)) {
 
467
         ret = DNDMSG_ERR;
 
468
         goto err;
 
469
      }
 
470
 
 
471
      if (!DnDMsg_AppendArg(msg, data, argSz)) {
 
472
         ret = DNDMSG_NOMEM;
 
473
         goto err;
 
474
      }
 
475
      readArgsSz += argSz + sizeof (uint32);
 
476
      free(data);
 
477
   }
 
478
 
 
479
   ASSERT(ret == DNDMSG_SUCCESS);
 
480
   return ret;
 
481
 
 
482
err:
 
483
   if (data) {
 
484
      free(data);
 
485
   }
 
486
 
 
487
   count = DynBufArray_Count(&msg->args);
 
488
   for (i = 0; i < count; ++i) {
 
489
      DynBuf *b = DynArray_AddressOf(&msg->args, i);
 
490
      DynBuf_Destroy(b);
 
491
   }
 
492
   /*
 
493
    * DnDMsg_AppendArg relies on DynBufArray_Push, hence the count needs to be
 
494
    * reset.
 
495
    */
 
496
   DynBufArray_SetCount(&msg->args, 0);
 
497
 
 
498
   return ret;
 
499
}