~ubuntu-branches/ubuntu/maverick/samba/maverick-security

« back to all changes in this revision

Viewing changes to .pc/fix-too-many-open-files.patch/source3/smbd/files.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-01-29 06:16:15 UTC
  • mfrom: (0.27.9 upstream) (0.34.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100129061615-37hs6xqpsdhjq3ld
Tags: 2:3.4.5~dfsg-1ubuntu1
* Merge from debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/smb.conf:
    - Add "(Samba, Ubuntu)" to server string.
    - Comment out the default [homes] share, and add a comment about "valid users = %s"
      to show users how to restrict access to \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are allowed to create
      public shares in additon to authenticated ones.
    - add map to guest = Bad user, maps bad username to gues access.
  + debian/samba-common.conf:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/mksambapasswd.awk:
    - Do not add user with UID less than 1000 to smbpasswd.
  + debian/control: 
    - Make libswbclient0 replace/conflict with hardy's likewise-open.
    - Don't build against ctdb, since its not in main yet.
  + debian/rules:
    - Enable "native" PIE hardening.
    - Add BIND_NOW to maximize benefit of RELRO hardening.
  + Add ufw integration:
    - Created debian/samba.ufw.profile.
    - debian/rules, debian/samba.dirs, debian/samba.files: install
  + Add apoort hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + debian/rules, debian/samba.if-up: allow "NetworkManager" as a recognized address
    family... it's obviously /not/ an address family, but it's what gets
    sent when using NM, so we'll cope for now.  (LP: #462169). Taken from karmic-proposed.
  + debian/control: Recommend keyutils for smbfs (LP: #493565)
  + Dropped patches:
    - debian/patches/security-CVE-2009-3297.patch: No longer needed
    - debian/patches/fix-too-many-open-files.patch: No longer needed

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* 
2
 
   Unix SMB/CIFS implementation.
3
 
   Files[] structure handling
4
 
   Copyright (C) Andrew Tridgell 1998
5
 
   
6
 
   This program is free software; you can redistribute it and/or modify
7
 
   it under the terms of the GNU General Public License as published by
8
 
   the Free Software Foundation; either version 3 of the License, or
9
 
   (at your option) any later version.
10
 
   
11
 
   This program is distributed in the hope that it will be useful,
12
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 
   GNU General Public License for more details.
15
 
   
16
 
   You should have received a copy of the GNU General Public License
17
 
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 
*/
19
 
 
20
 
#include "includes.h"
21
 
#include "smbd/globals.h"
22
 
 
23
 
#define VALID_FNUM(fnum)   (((fnum) >= 0) && ((fnum) < real_max_open_files))
24
 
 
25
 
#define FILE_HANDLE_OFFSET 0x1000
26
 
 
27
 
/****************************************************************************
28
 
 Return a unique number identifying this fsp over the life of this pid.
29
 
****************************************************************************/
30
 
 
31
 
static unsigned long get_gen_count(void)
32
 
{
33
 
        if ((++file_gen_counter) == 0)
34
 
                return ++file_gen_counter;
35
 
        return file_gen_counter;
36
 
}
37
 
 
38
 
/****************************************************************************
39
 
 Find first available file slot.
40
 
****************************************************************************/
41
 
 
42
 
NTSTATUS file_new(struct smb_request *req, connection_struct *conn,
43
 
                  files_struct **result)
44
 
{
45
 
        int i;
46
 
        files_struct *fsp;
47
 
 
48
 
        /* we want to give out file handles differently on each new
49
 
           connection because of a common bug in MS clients where they try to
50
 
           reuse a file descriptor from an earlier smb connection. This code
51
 
           increases the chance that the errant client will get an error rather
52
 
           than causing corruption */
53
 
        if (first_file == 0) {
54
 
                first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
55
 
        }
56
 
 
57
 
        /* TODO: Port the id-tree implementation from Samba4 */
58
 
 
59
 
        i = bitmap_find(file_bmap, first_file);
60
 
        if (i == -1) {
61
 
                DEBUG(0,("ERROR! Out of file structures\n"));
62
 
                /* TODO: We have to unconditionally return a DOS error here,
63
 
                 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
64
 
                 * NTSTATUS negotiated */
65
 
                return NT_STATUS_TOO_MANY_OPENED_FILES;
66
 
        }
67
 
 
68
 
        fsp = SMB_MALLOC_P(files_struct);
69
 
        if (!fsp) {
70
 
                return NT_STATUS_NO_MEMORY;
71
 
        }
72
 
 
73
 
        ZERO_STRUCTP(fsp);
74
 
 
75
 
        fsp->fh = SMB_MALLOC_P(struct fd_handle);
76
 
        if (!fsp->fh) {
77
 
                SAFE_FREE(fsp);
78
 
                return NT_STATUS_NO_MEMORY;
79
 
        }
80
 
 
81
 
        ZERO_STRUCTP(fsp->fh);
82
 
 
83
 
        fsp->fh->ref_count = 1;
84
 
        fsp->fh->fd = -1;
85
 
 
86
 
        fsp->conn = conn;
87
 
        fsp->fh->gen_id = get_gen_count();
88
 
        GetTimeOfDay(&fsp->open_time);
89
 
 
90
 
        first_file = (i+1) % real_max_open_files;
91
 
 
92
 
        bitmap_set(file_bmap, i);
93
 
        files_used++;
94
 
 
95
 
        fsp->fnum = i + FILE_HANDLE_OFFSET;
96
 
        SMB_ASSERT(fsp->fnum < 65536);
97
 
 
98
 
        string_set(&fsp->fsp_name,"");
99
 
        
100
 
        DLIST_ADD(Files, fsp);
101
 
 
102
 
        DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
103
 
                 i, fsp->fnum, files_used));
104
 
 
105
 
        if (req != NULL) {
106
 
                req->chain_fsp = fsp;
107
 
        }
108
 
 
109
 
        /* A new fsp invalidates the positive and
110
 
          negative fsp_fi_cache as the new fsp is pushed
111
 
          at the start of the list and we search from
112
 
          a cache hit to the *end* of the list. */
113
 
 
114
 
        ZERO_STRUCT(fsp_fi_cache);
115
 
 
116
 
        conn->num_files_open++;
117
 
 
118
 
        *result = fsp;
119
 
        return NT_STATUS_OK;
120
 
}
121
 
 
122
 
/****************************************************************************
123
 
 Close all open files for a connection.
124
 
****************************************************************************/
125
 
 
126
 
void file_close_conn(connection_struct *conn)
127
 
{
128
 
        files_struct *fsp, *next;
129
 
        
130
 
        for (fsp=Files;fsp;fsp=next) {
131
 
                next = fsp->next;
132
 
                if (fsp->conn == conn) {
133
 
                        close_file(NULL, fsp, SHUTDOWN_CLOSE);
134
 
                }
135
 
        }
136
 
}
137
 
 
138
 
/****************************************************************************
139
 
 Close all open files for a pid and a vuid.
140
 
****************************************************************************/
141
 
 
142
 
void file_close_pid(uint16 smbpid, int vuid)
143
 
{
144
 
        files_struct *fsp, *next;
145
 
        
146
 
        for (fsp=Files;fsp;fsp=next) {
147
 
                next = fsp->next;
148
 
                if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
149
 
                        close_file(NULL, fsp, SHUTDOWN_CLOSE);
150
 
                }
151
 
        }
152
 
}
153
 
 
154
 
/****************************************************************************
155
 
 Initialise file structures.
156
 
****************************************************************************/
157
 
 
158
 
#define MAX_OPEN_FUDGEFACTOR 20
159
 
 
160
 
void file_init(void)
161
 
{
162
 
        int request_max_open_files = lp_max_open_files();
163
 
        int real_lim;
164
 
 
165
 
        /*
166
 
         * Set the max_open files to be the requested
167
 
         * max plus a fudgefactor to allow for the extra
168
 
         * fd's we need such as log files etc...
169
 
         */
170
 
        real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
171
 
 
172
 
        real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
173
 
 
174
 
        if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536)
175
 
                real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
176
 
 
177
 
        if(real_max_open_files != request_max_open_files) {
178
 
                DEBUG(1,("file_init: Information only: requested %d \
179
 
open files, %d are available.\n", request_max_open_files, real_max_open_files));
180
 
        }
181
 
 
182
 
        SMB_ASSERT(real_max_open_files > 100);
183
 
 
184
 
        file_bmap = bitmap_allocate(real_max_open_files);
185
 
        
186
 
        if (!file_bmap) {
187
 
                exit_server("out of memory in file_init");
188
 
        }
189
 
}
190
 
 
191
 
/****************************************************************************
192
 
 Close files open by a specified vuid.
193
 
****************************************************************************/
194
 
 
195
 
void file_close_user(int vuid)
196
 
{
197
 
        files_struct *fsp, *next;
198
 
 
199
 
        for (fsp=Files;fsp;fsp=next) {
200
 
                next=fsp->next;
201
 
                if (fsp->vuid == vuid) {
202
 
                        close_file(NULL, fsp, SHUTDOWN_CLOSE);
203
 
                }
204
 
        }
205
 
}
206
 
 
207
 
/*
208
 
 * Walk the files table until "fn" returns non-NULL
209
 
 */
210
 
 
211
 
struct files_struct *file_walk_table(
212
 
        struct files_struct *(*fn)(struct files_struct *fsp,
213
 
                                   void *private_data),
214
 
        void *private_data)
215
 
{
216
 
        struct files_struct *fsp, *next;
217
 
 
218
 
        for (fsp = Files; fsp; fsp = next) {
219
 
                struct files_struct *ret;
220
 
                next = fsp->next;
221
 
                ret = fn(fsp, private_data);
222
 
                if (ret != NULL) {
223
 
                        return ret;
224
 
                }
225
 
        }
226
 
        return NULL;
227
 
}
228
 
 
229
 
/****************************************************************************
230
 
 Debug to enumerate all open files in the smbd.
231
 
****************************************************************************/
232
 
 
233
 
void file_dump_open_table(void)
234
 
{
235
 
        int count=0;
236
 
        files_struct *fsp;
237
 
 
238
 
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
239
 
                DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n",
240
 
                        count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id,
241
 
                          file_id_string_tos(&fsp->file_id)));
242
 
        }
243
 
}
244
 
 
245
 
/****************************************************************************
246
 
 Find a fsp given a file descriptor.
247
 
****************************************************************************/
248
 
 
249
 
files_struct *file_find_fd(int fd)
250
 
{
251
 
        int count=0;
252
 
        files_struct *fsp;
253
 
 
254
 
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
255
 
                if (fsp->fh->fd == fd) {
256
 
                        if (count > 10) {
257
 
                                DLIST_PROMOTE(Files, fsp);
258
 
                        }
259
 
                        return fsp;
260
 
                }
261
 
        }
262
 
 
263
 
        return NULL;
264
 
}
265
 
 
266
 
/****************************************************************************
267
 
 Find a fsp given a device, inode and file_id.
268
 
****************************************************************************/
269
 
 
270
 
files_struct *file_find_dif(struct file_id id, unsigned long gen_id)
271
 
{
272
 
        int count=0;
273
 
        files_struct *fsp;
274
 
 
275
 
        for (fsp=Files;fsp;fsp=fsp->next,count++) {
276
 
                /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
277
 
                if (file_id_equal(&fsp->file_id, &id) &&
278
 
                    fsp->fh->gen_id == gen_id ) {
279
 
                        if (count > 10) {
280
 
                                DLIST_PROMOTE(Files, fsp);
281
 
                        }
282
 
                        /* Paranoia check. */
283
 
                        if ((fsp->fh->fd == -1) &&
284
 
                            (fsp->oplock_type != NO_OPLOCK) &&
285
 
                            (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
286
 
                                DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \
287
 
oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, 
288
 
                                         file_id_string_tos(&fsp->file_id),
289
 
                                         (unsigned int)fsp->fh->gen_id,
290
 
                                         (unsigned int)fsp->oplock_type ));
291
 
                                smb_panic("file_find_dif");
292
 
                        }
293
 
                        return fsp;
294
 
                }
295
 
        }
296
 
 
297
 
        return NULL;
298
 
}
299
 
 
300
 
/****************************************************************************
301
 
 Check if an fsp still exists.
302
 
****************************************************************************/
303
 
 
304
 
files_struct *file_find_fsp(files_struct *orig_fsp)
305
 
{
306
 
        files_struct *fsp;
307
 
 
308
 
        for (fsp=Files;fsp;fsp=fsp->next) {
309
 
                if (fsp == orig_fsp)
310
 
                        return fsp;
311
 
        }
312
 
 
313
 
        return NULL;
314
 
}
315
 
 
316
 
/****************************************************************************
317
 
 Find the first fsp given a device and inode.
318
 
 We use a singleton cache here to speed up searching from getfilepathinfo
319
 
 calls.
320
 
****************************************************************************/
321
 
 
322
 
files_struct *file_find_di_first(struct file_id id)
323
 
{
324
 
        files_struct *fsp;
325
 
 
326
 
        if (file_id_equal(&fsp_fi_cache.id, &id)) {
327
 
                /* Positive or negative cache hit. */
328
 
                return fsp_fi_cache.fsp;
329
 
        }
330
 
 
331
 
        fsp_fi_cache.id = id;
332
 
 
333
 
        for (fsp=Files;fsp;fsp=fsp->next) {
334
 
                if (file_id_equal(&fsp->file_id, &id)) {
335
 
                        /* Setup positive cache. */
336
 
                        fsp_fi_cache.fsp = fsp;
337
 
                        return fsp;
338
 
                }
339
 
        }
340
 
 
341
 
        /* Setup negative cache. */
342
 
        fsp_fi_cache.fsp = NULL;
343
 
        return NULL;
344
 
}
345
 
 
346
 
/****************************************************************************
347
 
 Find the next fsp having the same device and inode.
348
 
****************************************************************************/
349
 
 
350
 
files_struct *file_find_di_next(files_struct *start_fsp)
351
 
{
352
 
        files_struct *fsp;
353
 
 
354
 
        for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
355
 
                if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
356
 
                        return fsp;
357
 
                }
358
 
        }
359
 
 
360
 
        return NULL;
361
 
}
362
 
 
363
 
/****************************************************************************
364
 
 Find a fsp that is open for printing.
365
 
****************************************************************************/
366
 
 
367
 
files_struct *file_find_print(void)
368
 
{
369
 
        files_struct *fsp;
370
 
 
371
 
        for (fsp=Files;fsp;fsp=fsp->next) {
372
 
                if (fsp->print_file) {
373
 
                        return fsp;
374
 
                }
375
 
        } 
376
 
 
377
 
        return NULL;
378
 
}
379
 
 
380
 
/****************************************************************************
381
 
 Find any fsp open with a pathname below that of an already open path.
382
 
****************************************************************************/
383
 
 
384
 
bool file_find_subpath(files_struct *dir_fsp)
385
 
{
386
 
        files_struct *fsp;
387
 
        size_t dlen;
388
 
        char *d_fullname = talloc_asprintf(talloc_tos(),
389
 
                                        "%s/%s",
390
 
                                        dir_fsp->conn->connectpath,
391
 
                                        dir_fsp->fsp_name);
392
 
        if (!d_fullname) {
393
 
                return false;
394
 
        }
395
 
 
396
 
        dlen = strlen(d_fullname);
397
 
 
398
 
        for (fsp=Files;fsp;fsp=fsp->next) {
399
 
                char *d1_fullname;
400
 
 
401
 
                if (fsp == dir_fsp) {
402
 
                        continue;
403
 
                }
404
 
 
405
 
                d1_fullname = talloc_asprintf(talloc_tos(),
406
 
                                        "%s/%s",
407
 
                                        fsp->conn->connectpath,
408
 
                                        fsp->fsp_name);
409
 
 
410
 
                /*
411
 
                 * If the open file has a path that is a longer
412
 
                 * component, then it's a subpath.
413
 
                 */
414
 
                if (strnequal(d_fullname, d1_fullname, dlen) &&
415
 
                                (d1_fullname[dlen] == '/')) {
416
 
                        TALLOC_FREE(d1_fullname);
417
 
                        TALLOC_FREE(d_fullname);
418
 
                        return true;
419
 
                }
420
 
                TALLOC_FREE(d1_fullname);
421
 
        }
422
 
 
423
 
        TALLOC_FREE(d_fullname);
424
 
        return false;
425
 
}
426
 
 
427
 
/****************************************************************************
428
 
 Sync open files on a connection.
429
 
****************************************************************************/
430
 
 
431
 
void file_sync_all(connection_struct *conn)
432
 
{
433
 
        files_struct *fsp, *next;
434
 
 
435
 
        for (fsp=Files;fsp;fsp=next) {
436
 
                next=fsp->next;
437
 
                if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
438
 
                        sync_file(conn, fsp, True /* write through */);
439
 
                }
440
 
        }
441
 
}
442
 
 
443
 
/****************************************************************************
444
 
 Free up a fsp.
445
 
****************************************************************************/
446
 
 
447
 
void file_free(struct smb_request *req, files_struct *fsp)
448
 
{
449
 
        DLIST_REMOVE(Files, fsp);
450
 
 
451
 
        string_free(&fsp->fsp_name);
452
 
 
453
 
        TALLOC_FREE(fsp->fake_file_handle);
454
 
 
455
 
        if (fsp->fh->ref_count == 1) {
456
 
                SAFE_FREE(fsp->fh);
457
 
        } else {
458
 
                fsp->fh->ref_count--;
459
 
        }
460
 
 
461
 
        if (fsp->notify) {
462
 
                notify_remove(fsp->conn->notify_ctx, fsp);
463
 
                TALLOC_FREE(fsp->notify);
464
 
        }
465
 
 
466
 
        /* Ensure this event will never fire. */
467
 
        TALLOC_FREE(fsp->oplock_timeout);
468
 
 
469
 
        /* Ensure this event will never fire. */
470
 
        TALLOC_FREE(fsp->update_write_time_event);
471
 
 
472
 
        bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
473
 
        files_used--;
474
 
 
475
 
        DEBUG(5,("freed files structure %d (%d used)\n",
476
 
                 fsp->fnum, files_used));
477
 
 
478
 
        fsp->conn->num_files_open--;
479
 
 
480
 
        if ((req != NULL) && (fsp == req->chain_fsp)) {
481
 
                req->chain_fsp = NULL;
482
 
        }
483
 
 
484
 
        /* Closing a file can invalidate the positive cache. */
485
 
        if (fsp == fsp_fi_cache.fsp) {
486
 
                ZERO_STRUCT(fsp_fi_cache);
487
 
        }
488
 
 
489
 
        /* Drop all remaining extensions. */
490
 
        while (fsp->vfs_extension) {
491
 
                vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp);
492
 
        }
493
 
 
494
 
        /* this is paranoia, just in case someone tries to reuse the
495
 
           information */
496
 
        ZERO_STRUCTP(fsp);
497
 
 
498
 
        SAFE_FREE(fsp);
499
 
}
500
 
 
501
 
/****************************************************************************
502
 
 Get an fsp from a 16 bit fnum.
503
 
****************************************************************************/
504
 
 
505
 
files_struct *file_fnum(uint16 fnum)
506
 
{
507
 
        files_struct *fsp;
508
 
        int count=0;
509
 
 
510
 
        for (fsp=Files;fsp;fsp=fsp->next, count++) {
511
 
                if (fsp->fnum == fnum) {
512
 
                        if (count > 10) {
513
 
                                DLIST_PROMOTE(Files, fsp);
514
 
                        }
515
 
                        return fsp;
516
 
                }
517
 
        }
518
 
        return NULL;
519
 
}
520
 
 
521
 
/****************************************************************************
522
 
 Get an fsp from a packet given the offset of a 16 bit fnum.
523
 
****************************************************************************/
524
 
 
525
 
files_struct *file_fsp(struct smb_request *req, uint16 fid)
526
 
{
527
 
        files_struct *fsp;
528
 
 
529
 
        if ((req != NULL) && (req->chain_fsp != NULL)) {
530
 
                return req->chain_fsp;
531
 
        }
532
 
 
533
 
        fsp = file_fnum(fid);
534
 
        if ((fsp != NULL) && (req != NULL)) {
535
 
                req->chain_fsp = fsp;
536
 
        }
537
 
        return fsp;
538
 
}
539
 
 
540
 
/****************************************************************************
541
 
 Duplicate the file handle part for a DOS or FCB open.
542
 
****************************************************************************/
543
 
 
544
 
void dup_file_fsp(struct smb_request *req, files_struct *from,
545
 
                      uint32 access_mask, uint32 share_access,
546
 
                      uint32 create_options, files_struct *to)
547
 
{
548
 
        SAFE_FREE(to->fh);
549
 
 
550
 
        to->fh = from->fh;
551
 
        to->fh->ref_count++;
552
 
 
553
 
        to->file_id = from->file_id;
554
 
        to->initial_allocation_size = from->initial_allocation_size;
555
 
        to->mode = from->mode;
556
 
        to->file_pid = from->file_pid;
557
 
        to->vuid = from->vuid;
558
 
        to->open_time = from->open_time;
559
 
        to->access_mask = access_mask;
560
 
        to->share_access = share_access;
561
 
        to->oplock_type = from->oplock_type;
562
 
        to->can_lock = from->can_lock;
563
 
        to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
564
 
        if (!CAN_WRITE(from->conn)) {
565
 
                to->can_write = False;
566
 
        } else {
567
 
                to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
568
 
        }
569
 
        to->print_file = from->print_file;
570
 
        to->modified = from->modified;
571
 
        to->is_directory = from->is_directory;
572
 
        to->aio_write_behind = from->aio_write_behind;
573
 
        string_set(&to->fsp_name,from->fsp_name);
574
 
}